<?php
/**
 * BaseTemplate class for the Timeless skin
 *
 * @ingroup Skins
 */
class TimelessTemplate extends BaseTemplate {
	/**
	 * Outputs the entire contents of the page
	 */
	public function execute() {
		$pileOfTools = $this->getPageTools();

		$this->html( 'headelement' );
		?>
		<div id="mw-wrapper">
			<div id="mw-header-container" class="ts-container">
			<div id="mw-header" class="ts-inner">
				<div id="user-tools">
					<?php $this->outputUserLinks(); ?>
				</div>
				<?php
				$this->outputLogo( 'p-logo-text', 'text' );
				$this->outputSearch();
				?>
			</div>
			<div class="visual-clear"></div>
			</div>

			<div id="mw-header-hack" class="color-bar">
				<div class="color-middle-container">
					<div class="color-middle"></div>
				</div>
				<div class="color-left"></div>
				<div class="color-right"></div>
			</div>
			<div id="mw-header-nav-hack">
			<div class="color-bar">
				<div class="color-middle-container">
					<div class="color-middle"></div>
				</div>
				<div class="color-left"></div>
				<div class="color-right"></div>
			</div>
			</div>
			<div id="menus-cover"></div>

			<div id="mw-content-container" class="ts-container">
			<div id="mw-content-block" class="ts-inner">
				<div id="mw-site-navigation">
					<?php
					$this->outputLogo( 'p-logo', 'image' );
					$this->outputSiteNavigation();

					$siteTools = $this->assemblePortlet( array(
						'id' => 'p-sitetools',
						'headerMessage' => 'timeless-sitetools',
						'content' => $pileOfTools['general']
					) );
					$this->outputSidebarChunk( 'site-tools', 'timeless-sitetools', $siteTools );
					?>
				</div>
				<div id="mw-related-navigation">
					<?php
					$pageTools = '';
					if ( count( $pileOfTools['page-secondary'] ) > 0 ) {
						$pageTools .= $this->assemblePortlet( array(
							'id' => 'p-pageactions',
							'headerMessage' => 'timeless-pageactions',
							'content' => $pileOfTools['page-secondary'],
						) );
					}
					if ( count( $pileOfTools['user'] ) > 0 ) {
						$pageTools .= $this->assemblePortlet( array(
							'id' => 'p-userpagetools',
							'headerMessage' => 'timeless-userpagetools',
							'content' => $pileOfTools['user'],
						) );
					}
					$pageTools .= $this->assemblePortlet( array(
						'id' => 'p-pagemisc',
						'headerMessage' => 'timeless-pagemisc',
						'content' => $pileOfTools['page-tertiary'],
					) );
					$this->outputSidebarChunk( 'page-tools', 'timeless-pageactions', $pageTools );

					$this->outputInterlanguageLinks();
					$this->outputCategories();
					?>
				</div>
				<div id="mw-content">
				<div class="mw-body" role="main">
					<?php
					if ( $this->data['sitenotice'] ) {
						?>
						<div id="siteNotice"><?php $this->html( 'sitenotice' ) ?></div>
						<?php
					}
					if ( $this->data['newtalk'] ) {
						?>
						<div class="usermessage"><?php $this->html( 'newtalk' ) ?></div>
						<?php
					}
					echo $this->getIndicators();
					?>

					<h1 class="firstHeading">
						<?php $this->html( 'title' ) ?>
					</h1>
					<div id="page-header-links">
					<?php
						echo $this->assemblePortlet( array(
							'id' => 'p-namespaces',
							'headerMessage' => 'timeless-namespaces',
							'content' => $pileOfTools['namespaces'],
						) );
					?>
					<?php
						echo $this->assemblePortlet( array(
							'id' => 'p-pagetools',
							'headerMessage' => 'timeless-pagetools',
							'content' => $pileOfTools['page-primary'],
						) );
					?>
					</div>
					<div class="visual-clear"></div>
					<div class="mw-body-content">
						<div id="contentSub">
							<?php
							if ( $this->data['subtitle'] ) {
								?>
								<p><?php $this->html( 'subtitle' ) ?></p>
								<?php
							}
							if ( $this->data['undelete'] ) {
								?>
								<p><?php $this->html( 'undelete' ) ?></p>
								<?php
							}
							?>
						</div>

						<?php
						$this->html( 'bodytext' );
						?>
						<div class="visual-clear"></div>
					</div>
				</div>
				</div>
			<?php
				if ( $this->data['catlinks'] ) {
					$this->html( 'catlinks' );
				}
				$this->html( 'dataAfterContent' );
			?>
			<div class="visual-clear"></div>
			</div>
			</div>

			<div id="mw-footer-container" class="ts-container">
			<div id="mw-footer" class="ts-inner">
				<ul role="contentinfo" id="footer-icons">
					<?php
					foreach ( $this->getFooterIcons( 'icononly' ) as $blockName => $footerIcons ) {
						?>
						<li>
							<?php
							foreach ( $footerIcons as $icon ) {
								echo $this->getSkin()->makeFooterIcon( $icon );
							}
							?>
						</li>
						<?php
					}
					?>
				</ul>
				<?php
				foreach ( $this->getFooterLinks() as $category => $links ) {
					?>
					<ul role="contentinfo" id="footer-<?php echo Sanitizer::escapeId( $category ) ?>">
						<?php
						foreach ( $links as $key ) {
							?>
							<li><?php $this->html( $key ) ?></li>
							<?php
						}
						?>
					</ul>
					<?php
				}
				?>
			</div>
			</div>
		</div>

		<?php $this->printTrail() ?>
		</body></html>

		<?php
	}

	/**
	 * Returns a single sidebar portlet of any kind (monobook style)
	 */
	private function assemblePortlet( $box ) {
		if ( !$box['content'] ) {
			return;
		}
		if ( !isset( $box['class'] ) ) {
			$box['class'] = 'mw-portlet';
		} else {
			$box['class'] .= ' mw-portlet';
		}

		$content = '<div role="navigation" class="' . $box['class'] . '" id="' . Sanitizer::escapeId( $box['id'] ) . '"' . Linker::tooltip( $box['id'] ) . '>';
		$content .= '<h3>';
			if ( isset( $box['headerMessage'] ) ) {
				$content .= $this->getMsg( $box['headerMessage'] )->escaped();
			} else {
				$content .= htmlspecialchars( $box['header'] );
			}
		$content .= '</h3>';
		if ( is_array( $box['content'] ) ) {
			$content .= '<ul>';
			foreach ( $box['content'] as $key => $item ) {
				$content .= $this->makeListItem( $key, $item );
			}
			$content .= '</ul>';
		} else {
			$content .= $box['content'];
		}
		$content .= '</div>';

		return $content;
	}

	/**
	 * Makes links for navigation lists.
	 *
	 * Modified to add a <span> around <a> content in navigation lists; everything else is
	 * basically the same as in BaseTemplate, just with extra stuff removed.
	 *
	 * Can't just use the original's options['wrapper'] because it's a piece of crap and spews
	 * infinite errors on the page.
	 */
	function makeLink( $key, $item, $options = array() ) {
		if ( isset( $item['text'] ) ) {
			$text = $item['text'];
		} else {
			$text = $this->translator->translate( isset( $item['msg'] ) ? $item['msg'] : $key );
		}

		$html = htmlspecialchars( $text );
		$html = '<span>' . $html . '</span>';

		if ( isset( $item['href'] ) ) {
			$attrs = $item;
			foreach ( array( 'single-id', 'text', 'msg', 'tooltiponly', 'context', 'primary' ) as $k ) {
				unset( $attrs[$k] );
			}

			if ( isset( $item['id'] ) && !isset( $item['single-id'] ) ) {
				$item['single-id'] = $item['id'];
			}
			if ( isset( $item['single-id'] ) ) {
				if ( isset( $item['tooltiponly'] ) && $item['tooltiponly'] ) {
					$title = Linker::titleAttrib( $item['single-id'] );
					if ( $title !== false ) {
						$attrs['title'] = $title;
					}
				} else {
					$tip = Linker::tooltipAndAccesskeyAttribs( $item['single-id'] );
					if ( isset( $tip['title'] ) && $tip['title'] !== false ) {
						$attrs['title'] = $tip['title'];
					}
					if ( isset( $tip['accesskey'] ) && $tip['accesskey'] !== false ) {
						$attrs['accesskey'] = $tip['accesskey'];
					}
				}
			}
			$html = Html::rawElement( 'a', $attrs, $html );
		}

		return $html;
	}

	/**
	 * Outputs a sidebar-chunk containing one or more portlets
	 */
	private function outputSidebarChunk( $id, $headerMessage, $content ) {
		echo '<div id="' . $id . '" class="sidebar-chunk">';
		echo '<h2><span>' . $this->getMsg( $headerMessage )->escaped() . '</span><div class="pokey"></div></h2>';
		echo '<div class="sidebar-inner">' . $content . '</div></div>';
	}

	/**
	 * Outputs the logo and (optionally) site title
	 */
	private function outputLogo( $id = 'p-logo', $part = 'both' ) {
		?>
		<div id="<?php echo $id ?>" class="mw-portlet" role="banner">
			<?php
			if ( $part !== 'text' ) {
				?>
				<a
					class="mw-wiki-logo"
					href="<?php echo htmlspecialchars( $this->data['nav_urls']['mainpage']['href'] )
				?>" <?php
				echo Xml::expandAttributes( Linker::tooltipAndAccesskeyAttribs( 'p-logo' ) )
				?>></a>
				<?php
			}
			if ( $part !== 'image' ) {
				$titleClass = '';
				$siteTitle = $this->getMsg( 'timeless-sitetitle' )->escaped();
				// width is 11em; 13 characters will probably fit?
				if ( mb_strlen( $siteTitle ) > 13 ) {
					$titleClass = 'long';
				}
				?>
				<a id="p-banner" class="mw-wiki-title <?php echo $titleClass ?>" href="<?php echo htmlspecialchars( $this->data['nav_urls']['mainpage']['href'] ) ?>">
					<?php echo $siteTitle ?>
				</a>
				<?php
			}
			?>
		</div>
		<?php
	}

	/**
	 * Outputs the search
	 */
	private function outputSearch() {
		?>
		<div class="mw-portlet" id="p-search">
			<h3<?php $this->html( 'userlangattributes' ) ?>>
				<label for="searchInput"><?php echo $this->getMsg( 'search' )->parse() ?></label>
			</h3>
			<form action="<?php $this->text( 'wgScript' ) ?>" id="searchform">
				<div id="simpleSearch">
				<div id="searchInput-container">
					<?php
					echo $this->makeSearchInput( array(
						'id' => 'searchInput',
						'placeholder' => $this->getMsg( 'timeless-search-placeholder' )->escaped(),
					) );
					?>
				</div>
				<?php
				echo Html::hidden( 'title', $this->get( 'searchtitle' ) );
				echo $this->makeSearchButton(
					'fulltext',
					array( 'id' => 'mw-searchButton', 'class' => 'searchButton mw-fallbackSearchButton' )
				);
				echo $this->makeSearchButton(
					'go',
					array( 'id' => 'searchButton', 'class' => 'searchButton' )
				);
				?>
				</div>
			</form>
		</div>
		<?php
	}

	/**
	 * Outputs the sidebar
	 */
	private function outputSiteNavigation() {
		$sidebar = $this->getSidebar();
		$content = '';

		$sidebar['SEARCH'] = false; // Already hardcoded into header
		$sidebar['TOOLBOX'] = false; // Parsed as part of pageTools
		$sidebar['LANGUAGES'] = false; // Forcibly removed to separate chunk

		foreach ( $sidebar as $boxName => $box ) {
			if ( $boxName === false ) {
				continue;
			}
			$content .= $this->assemblePortlet( $box, true );
		}

		$this->outputSidebarChunk( 'site-navigation', 'navigation', $content );
	}

	/**
	 * Outputs user links portlet for header
	 */
	private function outputUserLinks() {
		$user = $this->getSkin()->getUser();
		?>
		<div id="p-personal">
		<h2>
			<span>
			<?php
			// Display status, and make a dropdown if logged in
			if ( $user->isLoggedIn() ) {
				$userName = $user->getName();
				// Make sure it fit firsts
				if ( mb_strlen( $userName ) < 12 ) {
					echo htmlspecialchars( $userName, ENT_QUOTES );
				} else {
					echo wfMessage( 'timeless-loggedin' )->escaped();
				}
			} else {
				echo wfMessage( 'timeless-anonymous' )->escaped();
			}
			?>
			</span>
			<div class="pokey"></div>
		</h2>
		<div id="p-personal-inner" class="dropdown">
		<div class="mw-portlet" role="navigation">
			<h3>
			<?php
			if ( $user->isLoggedIn() ) {
				echo wfMessage( 'timeless-loggedinas', $user->getName() )->parse();
			} else {
				echo wfMessage( 'timeless-notloggedin' )->parse();
			}
			?>
			</h3>
			<div class="p-body">
			<ul<?php $this->html( 'userlangattributes' ) ?>>
			<?php
				foreach ( $this->getPersonalTools() as $key => $item ) {
					if ( $key == 'userpage' ) {
						$item['links'][0]['text'] = wfMessage( 'timeless-userpage', $user->getName() )->text();
					}
					if ( $key == 'mytalk' ) {
						$item['links'][0]['text'] = wfMessage( 'timeless-talkpage', $user->getName() )->text();
					}
					echo $this->makeListItem( $key, $item );
				}
			?>
			</ul>
			</div>
		</div>
		</div>
		</div>
		<?php
	}

	/*
	 * Generates pile of all the tools
	 * Returns array of arrays of each kind (wouldn't it be nice if tools themselves just registered the type instead?)
	 */
	private function getPageTools() {
		$title = $this->getSkin()->getTitle();
		$namespace = $title->getNamespace();

		$sortedPileOfTools = array(
			'namespaces' => array(),
			'page-primary' => array(),
			'page-secondary' => array(),
			'user' => array(),
			'page-tertiary' => array(),
			'general' => array()
		);

		$pileOfTools = array();
		foreach ( $this->data['content_navigation'] as $navKey => $navBlock ) {
			/* Just use namespaces items as they are */
			if ( $navKey == 'namespaces' ) {
				if ( $namespace < 0 ) {
					// Put special page ns_pages in the more pile so they're not so lonely
					$sortedPileOfTools['page-tertiary'] = $navBlock;
				} else {
					$sortedPileOfTools['namespaces'] = $navBlock;
				}
			} else {
				$pileOfTools = array_merge( $pileOfTools, $navBlock );
			}
		}
		$pileOfTools = array_merge( $pileOfTools, $this->getToolbox() );
		if ( $namespace >= 0 ) {
			$pileOfTools['pagelog'] = array(
				'text' => $this->getMsg( 'timeless-pagelog' )->escaped(),
				'href' => SpecialPage::getTitleFor( 'Log', $title->getPrefixedText() )->getLocalURL(),
				'id' => 't-pagelog'
			);
		}
		$pileOfTools['more'] = array(
			'text' => $this->getMsg( 'timeless-more' )->escaped(),
			'id' => 'ca-more',
			'class' => 'dropdown-toggle'
		);
		if ( $this->data['language_urls'] ) {
			$pileOfTools['languages'] = array(
				'text' => $this->getMsg( 'timeless-languages' )->escaped(),
				'id' => 'ca-languages',
				'class' => 'dropdown-toggle'
			);
		}

		/* This is really dumb, but there is no sane way to do this. */
		foreach ( $pileOfTools as $navKey => $navBlock ) {
			$currentSet = null;

			if ( in_array( $navKey, array( 'watch', 'unwatch' ) ) ) {
				$currentSet = 'namespaces';
			} elseif ( in_array( $navKey, array( 'edit', 'view', 'history', 'contributions', 'addsection', 'more', 'languages' ) ) ) {
				$currentSet = 'page-primary';
			} elseif ( in_array( $navKey, array( 'delete', 'rename', 'protect', 'unprotect', 'viewsource', 'move' ) ) ) {
				$currentSet = 'page-secondary';
			} elseif (in_array( $navKey, array( 'blockip', 'userrights', 'log' ) ) ) {
				$currentSet = 'user';
			} elseif (in_array( $navKey, array( 'whatlinkshere', 'print', 'info', 'pagelog', 'recentchangeslinked', 'permalink' ) ) ) {
				$currentSet = 'page-tertiary';
			} else {
				$currentSet = 'general';
			}
			$sortedPileOfTools[$currentSet][$navKey] = $navBlock;
		}

		return $sortedPileOfTools;
	}

	/*
	 * Assemble and output array of categories, regardless of view mode
	 * Just using Skin or OutputPage functions doesn't respect view modes (preview, history, whatever)
	 */
	private function outputCategories() {
		global $wgContLang;

		$skin =  $this->getSkin();
		$title = $skin->getTitle();
		$catList = false;

		/* Get list from outputpage if in preview; otherwise get list from title */
		if ( in_array( $skin->getRequest()->getVal( 'action' ), array( 'submit', 'edit' ) ) ) {
			$allCats = array();
			/* Can't just use getCategoryLinks because there's no equivalent for Title */
			$allCats2 = $skin->getOutput()->getCategories();
			foreach ( $allCats2 as $displayName ) {
				$catTitle = Title::makeTitleSafe( NS_CATEGORY, $displayName );
				$allCats[] = $catTitle->getDBkey();
			}
		} else {
			/* This is probably to trim out some excessive stuff. Unless I was just high on cough syrup. */
			$allCats = array_keys( $title->getParentCategories() );

			$len = strlen( $wgContLang->getNsText( NS_CATEGORY ) . ':' );
			foreach ( $allCats as $i => $catName ) {
				$allCats[$i] = substr( $catName, $len );
			}
		}
		if ( count( $allCats ) > 0 ) {
			$dbr = wfGetDB( DB_SLAVE );
			$res = $dbr->select(
				array( 'page', 'page_props' ),
				array( 'page_id', 'page_title' ),
				array(
					'page_title' => $allCats,
					'page_namespace' => NS_CATEGORY,
					'pp_propname' => 'hiddencat'
				),
				__METHOD__,
				array(),
				array( 'page_props' => array( 'JOIN', 'pp_page = page_id' ) )
			);
			$hiddenCats = array();
			foreach ( $res as $row ) {
				$hiddenCats[] = $row->page_title;
			}
			$normalCats = array_diff( $allCats, $hiddenCats );

			$normalCount = count( $normalCats );
			$hiddenCount = count( $hiddenCats );
			$count = $normalCount;

			/* Mostly consistent with how Skin does it. Doesn't have the classes. Either way can't be good for caching. */
			if (  $skin->getUser()->getBoolOption( 'showhiddencats' ) || $title->getNamespace() == NS_CATEGORY ) {
				$count += $hiddenCount;
			} else {
				/* We don't care if there are hidden ones. */
				$hiddenCount = 0;
			}

			/* Assemble the html because why not... */
			if ( $count ) {
				if ( $normalCount ) {
					$catHeader = 'categories';
				} else {
					$catHeader = 'hidden-categories';
				}
				$catList = '';
				if ( $normalCount ) {
					$catList .= $this->assembleCatList( $normalCats, 'catlist-normal', 'categories' );
				}
				if ( $hiddenCount ) {
					$catList .= $this->assembleCatList( $hiddenCats, 'catlist-hidden', 'hidden-categories' );
				}
			}
		}
		if ( $catList ) {
			$this->outputSidebarChunk( 'catlinks-sidebar', $catHeader, $catList );
		}
	}
	private function assembleCatList( $list, $id, $message ) {
		$catList = '<div class="mw-portlet" id="' . $id . '"><h3>' . $this->getMsg( $message )->escaped() . '</h3>';
		$catList .= '<ul>';
		foreach ( $list as $category) {
			$title = Title::makeTitleSafe( NS_CATEGORY, $category );
			if ( !$title ) {
				continue;
			}
			$category = Linker::link( $title, $title->getText() );
			$catList .=  '<li>' . $category . '</li>';
		}
		$catList .= '</ul></div>';

		return $catList;
	}

	/*
	 * Output interlanguage links block
	 */
	private function outputInterlanguageLinks() {
		if ( $this->data['language_urls'] ) {
			$msgObj = $this->getMsg( 'otherlanguages' )->escaped();
			$content = $this->assemblePortlet( array(
					'id' => 'p-lang',
					'header' => $msgObj,
					'generated' => false,
					'content' => $this->data['language_urls']
				) );

			$this->outputSidebarChunk( 'other-languages', 'timeless-languages', $content );
		}
	}
}