<?php
namespace wbb\data\board;
use wcf\system\language\LanguageFactory;
use wcf\system\WCF;

/**
 * Represents a board node element.
 * 
 * @author	Marcel Werk
 * @copyright	2001-2015 WoltLab GmbH
 * @license	WoltLab License <http://www.woltlab.com/license-agreement.html>
 * @package	com.woltlab.wbb
 * @subpackage	data.board
 * @category	Burning Board
 */
class DetailedBoardNode extends BoardNode {
	/**
	 * number of threads in this board
	 * @var	integer
	 */
	protected $threads = null;
	
	/**
	 * number of posts in this board
	 * @var	integer
	 */
	protected $posts = null;
	
	/**
	 * number of unread threads in this board
	 * @var	integer
	 */
	protected $unreadThreads = null;
	
	/**
	 * last post in this board
	 * @var	\wbb\data\thread\Thread
	 */
	protected $lastPost = null;
	
	/**
	 * true if the last post was loaded already
	 * @var	boolean
	 */
	protected $lastPostLoaded = false;
	
	/**
	 * list of sub boards
	 * @var	array<\wbb\data\board\BoardNode>
	 */
	protected $subBoards = null;
	
	/**
	 * Returns the number of clicks.
	 * 
	 * @return	integer
	 */
	public function getClicks() {
		return BoardCache::getInstance()->getClicks($this->board->boardID);
	}
	
	/**
	 * Returns the number of threads.
	 * 
	 * @return	integer
	 */
	public function getThreads() {
		if ($this->threads === null) {
			$this->threads = $this->board->getThreads();
			if (!$this->hasVisibleChildren()) {
				foreach ($this->children as $childNode) {
					$this->threads += $childNode->getThreads();
				}
			}
		}
		
		return $this->threads;
	}
	
	/**
	 * Returns the number of posts.
	 * 
	 * @return	integer
	 */
	public function getPosts() {
		if ($this->posts === null) {
			$this->posts = $this->board->getPosts();
			if (!$this->hasVisibleChildren()) {
				foreach ($this->children as $childNode) {
					$this->posts += $childNode->getPosts();
				}
			}
		}
		
		return $this->posts;
	}
	
	/**
	 * Returns the number of unread threads in this board.
	 * 
	 * @return	integer
	 */
	public function getUnreadThreads() {
		if ($this->unreadThreads === null) {
			$this->unreadThreads = BoardCache::getInstance()->getUnreadThreads($this->board->boardID);
			if (!$this->hasVisibleChildren() && ($this->board->isCategory() || !WBB_BOARD_LIST_ENABLE_SUB_BOARDS || !$this->board->showSubBoards || ($this->parentNode !== null && !$this->getParentNode()->isOpenNode()))) {
				foreach ($this->children as $childNode) {
					$this->unreadThreads += $childNode->getUnreadThreads();
				}
			}
		}
		
		return $this->unreadThreads;
	}
	
	/**
	 * Returns the last post.
	 * 
	 * @return	\wbb\data\thread\Thread
	 */
	public function getLastPost() {
		if (!$this->lastPostLoaded) {
			$this->lastPostLoaded = true;
			$cache = \wbb\system\cache\builder\ThreadIgnoreCacheBuilder::getInstance()->getData();
			if ($this->board->getPermission('canEnterBoard')) {
				if (LanguageFactory::getInstance()->multilingualismEnabled() && count(WCF::getUser()->getLanguageIDs())) {
					foreach (WCF::getUser()->getLanguageIDs() as $languageID) {
						$lastPost = BoardCache::getInstance()->getLastPost($this->board->boardID, $languageID);
						if ($lastPost !== null) {
							if ($this->lastPost === null || $lastPost->lastPostTime > $this->lastPost->lastPostTime) {
								if (isset($cache[WCF::getUser()->getUserID()])) {
									$threads = $cache[WCF::getUser()->getUserID()];
									if (in_array($lastPost->threadID, $threads)) {
										continue;
									}
								}
								$this->lastPost = $lastPost;
							}
						}
					}
				} else {
					$lastPost = BoardCache::getInstance()->getLastPost($this->board->boardID);
					if ($lastPost !== null) {
						if ($this->lastPost === null || $lastPost->lastPostTime > $lastPost->lastPostTime) {
							if (isset($cache[WCF::getUser()->getUserID()])) {
								$threads = $cache[WCF::getUser()->getUserID()];
								if (in_array($lastPost->threadID, $threads)) {
									return null;
								}
							}
							$this->lastPost = $lastPost;
						}
					}
				}
				if (!$this->hasVisibleChildren()) {
					foreach ($this->children as $childNode) {
						if (($childLastPost = $childNode->getLastPost()) !== null) {
							if ($this->lastPost === null || $childLastPost->lastPostTime < $childLastPost->lastPostTime) {
								if (isset($cache[WCF::getUser()->getUserID()])) {
									$threads = $cache[WCF::getUser()->getUserID()];
									if (in_array($childLastPost->threadID, $threads)) {
										return null;
									}
								}
								$this->lastPost = $childLastPost;
							}
						}
					}
				}
			}
		}
		
		return $this->lastPost;
	}
	
	/**
	 * Returns the sub boards.
	 * 
	 * @return	array
	 */
	public function getSubBoards() {
		if ($this->subBoards === null) {
			$this->subBoards = array();
			if (WBB_BOARD_LIST_ENABLE_SUB_BOARDS && $this->board->showSubBoards && !$this->hasVisibleChildren()) {
				foreach ($this->children as $childNode) {
					$this->subBoards[] = $childNode;
					$childSubBoards = $childNode->getSubBoards();
					if (count($childSubBoards)) {
						$this->subBoards = array_merge($this->subBoards, $childSubBoards);
					}
				}
			}
		}
		
		return $this->subBoards;
	}
	
	/**
	 * Returns sorted sub boards.
	 * 
	 * @return	array
	 */
	public function getSortedSubBoards() {
		$subBoards = $this->getSubBoards();
		usort($subBoards, function (BoardNode $boardNodeA, BoardNode $boardNodeB) {
			return strcoll($boardNodeA->getBoard()->title, $boardNodeB->getBoard()->title);
		});
		
		return $subBoards;
	}
	
	/**
	 * Returns true if a collapsible category is open.
	 * 
	 * @return	boolean
	 */
	public function isOpen() {
		if ($this->board !== null && $this->board->isCategory()) {
			return BoardCache::getInstance()->isOpen($this->board->boardID);
		}
		
		return true;
	}
	
	/**
	 * Returns true if this node is open.
	 * 
	 * @return	boolean
	 */
	public function isOpenNode() {
		return $this->isOpen() && $this->depth + 1 <= WBB_BOARD_LIST_DEPTH;
	}
	
	/**
	 * Returns true if this node has visible children.
	 * 
	 * @return	boolean
	 */
	public function hasVisibleChildren() {
		return ($this->hasChildren() && $this->isOpenNode());
	}
	
	/**
	 * Returns true if this node is collapsible.
	 * 
	 * @return	boolean
	 */
	public function isCollapsible() {
		if ($this->board !== null && $this->board->isCategory() && $this->hasChildren() && $this->depth + 1 <= WBB_BOARD_LIST_DEPTH) {
			return true;
		}
		
		return false;
	}
	
	/**
	 * @see	\Iterator::valid()
	 */
	public function valid() {
		return (parent::valid() && $this->isOpenNode());
	}
	
	/**
	 * Returns the users online list.
	 * 
	 * @return	array<\wcf\data\user\User>
	 */
	public function getUsersOnline() {
		return BoardCache::getInstance()->getUsersOnline($this->board->boardID);
	}
	
	/**
	 * Returns the parent node
	 *
	 * @return	\wbb\data\board\DetailedBoardNode
	 */
	public function getParentNode() {
		if ($this->parentNode === null) return null;
		
		return new DetailedBoardNode($this->parentNode->parentNode, $this->parentNode->getBoard(), $this->depth - 1);
	}
}
