<?php
/*****************************************************************************
 * ViewPhotoAlbum.php
 * Contains the photo album index controller
 *
 * Kabuki CMS (C) 2013-2015, Aaron van Geffen
 *****************************************************************************/

class ViewPhotoAlbum extends HTMLController
{
	protected $iterator;
	protected $total_count;
	protected $base_url;

	const PER_PAGE = 24;

	public function __construct($title = 'Photos - ' . SITE_TITLE)
	{
		// Ensure we're logged in at this point.
		if (!Registry::get('user')->isLoggedIn())
			throw new NotAllowedException();

		// Viewing an album?
		if (isset($_GET['tag']))
		{
			$tag = Tag::fromSlug($_GET['tag']);
			$id_tag = $tag->id_tag;
			$title = $tag->tag;
			$header_box = $this->getHeaderBox($tag);
		}
		// View the album root.
		else
		{
			$id_tag = 1;
			$tag = Tag::fromId($id_tag);
			$title = 'Albums';
		}

		// What page are we at?
		$page = isset($_GET['page']) ? (int) $_GET['page'] : 1;

		parent::__construct($title . ' - Page ' . $page . ' - ' . SITE_TITLE);
		if (isset($header_box))
			$this->page->adopt($header_box);

		// Can we do fancy things here?
		// !!! TODO: permission system?
		$buttons = $this->getAlbumButtons($tag);
		if (!empty($buttons))
			$this->page->adopt(new AlbumButtonBox($buttons));

		// Fetch subalbums, but only if we're on the first page.
		if ($page === 1)
		{
			$albums = $this->getAlbums($id_tag);
			$index = new AlbumIndex($albums);
			$this->page->adopt($index);
		}

		// Who contributed to this album?
		$contributors = $tag->getContributorList();

		// Enumerate possible filters
		$filters = ['' => [null, 'Show all photos']];
		foreach ($contributors as $contributor)
		{
			$filters[$contributor['slug']] = [$contributor['id_user'], sprintf('%s %s (%s photos)',
				$contributor['first_name'], $contributor['surname'], $contributor['num_assets'])];
		}

		// Limit to a particular uploader?
		$active_filter = $id_user_uploaded = null;
		if (!empty($_GET['by']))
		{
			if (!isset($filters[$_GET['by']]))
				throw new UnexpectedValueException('Invalid filter for this album or tag.');

			$active_filter = $_GET['by'];
			$id_user_uploaded = $filters[$active_filter][0];
		}

		// Load a photo mosaic for the current tag.
		list($mosaic, $total_count) = $this->getPhotoMosaic($id_tag, $id_user_uploaded, $page, !isset($is_person));
		if (isset($mosaic))
		{
			$index = new PhotosIndex($mosaic, Registry::get('user')->isAdmin());
			$this->page->adopt($index);
			if ($id_tag > 1)
				$index->setUrlSuffix('?in=' . $id_tag);
		}

		// Make a page index as needed, while we're at it.
		if ($total_count > self::PER_PAGE)
		{
			$index = new PageIndex([
				'recordCount' => $total_count,
				'items_per_page' => self::PER_PAGE,
				'start' => (isset($_GET['page']) ? $_GET['page'] - 1 : 0) * self::PER_PAGE,
				'base_url' => $tag->getUrl(),
				'page_slug' => 'page/%PAGE%/' . (isset($active_filter) ? '?by=' . $active_filter : ''),
				'index_class' => 'pagination-lg justify-content-around justify-content-lg-center',
			]);
			$this->page->adopt(new PageIndexWidget($index));
		}

		// Set the canonical url.
		$this->page->setCanonicalUrl($tag->getUrl() . ($page > 1 ? 'page/' . $page . '/' : ''));
	}

	public function getPhotoMosaic($id_tag, $id_user_uploaded, $page, $sort_linear)
	{
		// Create an iterator.
		list($this->iterator, $total_count) = AssetIterator::getByOptions([
			'id_tag' => $id_tag,
			'id_user_uploaded' => $id_user_uploaded,
			'order' => 'date_captured',
			'direction' => $sort_linear ? 'asc' : 'desc',
			'limit' => self::PER_PAGE,
			'page' => $page,
		], true);

		$mosaic = $total_count > 0 ? new PhotoMosaic($this->iterator) : null;
		return [$mosaic, $total_count];
	}

	private function getAlbums($id_tag)
	{
		// Fetch subalbums.
		$subalbums = Tag::getAlbums($id_tag);

		// What assets are we using?
		$id_assets = array_map(function($album) {
			return (int) $album['id_asset_thumb'];
		}, $subalbums);

		// Fetch assets for thumbnails.
		$assets = Asset::fromIds($id_assets, 'object');

		// Build album list.
		$albums = [];
		foreach ($subalbums as $album)
		{
			$albums[$album['id_tag']] = [
				'id_tag' => $album['id_tag'],
				'caption' => $album['tag'],
				'link' => BASEURL . '/' . $album['slug'] . '/',
				'thumbnail' => !empty($album['id_asset_thumb']) && isset($assets[$album['id_asset_thumb']])
					? $assets[$album['id_asset_thumb']]->getImage() : null,
			];
		}

		return $albums;
	}

	private function getAlbumButtons(Tag $tag)
	{
		$buttons = [];
		$user = Registry::get('user');

		if ($user->isLoggedIn())
		{
			$buttons[] = [
				'url' => BASEURL . '/download/?tag=' . $tag->id_tag,
				'caption' => 'Download album',
			];
		}

		if ($tag->id_parent != 0)
		{
			if ($tag->kind === 'Album')
			{
				$buttons[] = [
					'url' => BASEURL . '/uploadmedia/?tag=' . $tag->id_tag,
					'caption' => 'Upload photos here',
				];
			}

			if ($user->isAdmin())
			{
				if ($tag->kind === 'Album')
				{
					$buttons[] = [
						'url' => BASEURL . '/editalbum/?id=' . $tag->id_tag,
						'caption' => 'Edit album',
					];
				}
				elseif ($tag->kind === 'Person')
				{
					$buttons[] = [
						'url' => BASEURL . '/edittag/?id=' . $tag->id_tag,
						'caption' => 'Edit tag',
					];
				}
			}
		}

		if ($user->isAdmin() && (!isset($tag) || $tag->kind === 'Album'))
		{
			$buttons[] = [
				'url' => BASEURL . '/addalbum/?tag=' . $tag->id_tag,
				'caption' => 'Create subalbum',
			];
		}

		return $buttons;
	}

	private function getHeaderBox(Tag $tag)
	{
		// Can we go up a level?
		if ($tag->id_parent != 0)
		{
			$ptag = Tag::fromId($tag->id_parent);
			$back_link = BASEURL . '/' . (!empty($ptag->slug) ? $ptag->slug . '/' : '');
			$back_link_title = 'Back to &quot;' . $ptag->tag . '&quot;';
		}
		elseif ($tag->kind === 'Person')
		{
			$back_link = BASEURL . '/people/';
			$back_link_title = 'Back to &quot;People&quot;';
			$is_person = true;
		}

		$description = !empty($tag->description) ? $tag->description : '';
		return new AlbumHeaderBox($tag->tag, $description, $back_link, $back_link_title);
	}

	public function __destruct()
	{
		if (isset($this->iterator))
			$this->iterator->clean();
	}
}