<?php
declare(strict_types = 1);

require_once(__DIR__ . '/Gallery.class.php');

/**
 * Gestion des pages.
 *
 * @license https://www.gnu.org/licenses/gpl-3.0.html
 * @link https://www.igalerie.org/
 */
class GalleryPages extends Gallery
{
	/**
	 * Récupération des appareils photos.
	 *
	 * @return int
	 */
	public static function cameras(): int
	{
		Template::set('cameras', []);

		// Récupération des informations de la catégorie.
		$cat_infos = self::_getCategoryInfos(
			$_GET['cameras_id'] ?? 1, __('Appareils photos de %s')
		);
		if (!is_array($cat_infos))
		{
			return $cat_infos;
		}

		// Récupération des appareils photos.
		$sql = 'SELECT cam_m.camera_model_id,
					   camera_model_name,
					   camera_model_url,
					   cam_b.camera_brand_id,
					   camera_brand_name,
					   camera_brand_url,
					   COUNT(*) AS count
				  FROM {cameras_models} AS cam_m
			 LEFT JOIN {cameras_brands} AS cam_b USING (camera_brand_id)
		     LEFT JOIN {cameras_items} AS cam_i USING (camera_model_id)
		     LEFT JOIN {items} AS i USING (item_id)
		     LEFT JOIN {categories} AS cat USING (cat_id)
				 WHERE item_status = "1"
				   AND ' . SQL::catPerms() . '
				   AND ' . SQL::catPassword() . '
				   AND i.item_path LIKE :cat_path
			  GROUP BY cam_m.camera_model_id, cam_b.camera_brand_id
			  ORDER BY camera_brand_name ASC, camera_model_name ASC';
		DB::params(['cat_path' => $cat_infos['cat_id'] > 1
			? DB::likeEscape($cat_infos['cat_path']) . '/%'
			: '%']);
		if (!DB::execute($sql))
		{
			return -1;
		}
		$cameras = DB::fetchAll();
		$cameras_formated = [];
		foreach ($cameras as &$i)
		{
			$model = $i['camera_model_name'];
			$cameras_formated[] =
			[
				'count' => (int) $i['count'],
				'brand' => Metadata::getExifCameraMake($i['camera_brand_name']),
				'brand_link' => App::getURL($cat_infos['cat_type'] . '/' . $cat_infos['cat_id']
					. '/camera-brand/' . $i['camera_brand_id'] . '-' . $i['camera_brand_url']),
				'model' => isset(Metadata::MODELS[$model])
					? $model . ' (' . Metadata::MODELS[$model] . ')'
					: $model,
				'model_link' => App::getURL($cat_infos['cat_type'] . '/' . $cat_infos['cat_id']
					. '/camera-model/' . $i['camera_model_id'] . '-' . $i['camera_model_url'])
			];
		}
		Template::set('cameras', $cameras_formated);

		return 1;
	}

	/**
	 * Gestion de la page contact.
	 *
	 * @return int
	 */
	public static function contact(): int
	{
		// Permission d'accès.
		if (Config::$params['users'] && !Auth::$connected
		 && Config::$params['users_only_members_contact'])
		{
			return 0;
		}

		// Message de confirmation.
		if ($_GET['q'] == 'contact/confirm')
		{
			Report::success(__('Votre message a été envoyé.'));
			return 1;
		}

		// Paramètres de template.
		$contact = Config::$params['pages_params']['contact'];
		Template::set('contact',
		[
			'maxlength' => Mail::FIELDS_MAXLENGTH,
			'message' => Utility::isEmpty($contact['message']) ? NULL : $contact['message']
		]);
		Template::set('field_error', '');

		// On vérifie que la page est activée.
		if (!$contact['status'])
		{
			return 0;
		}

		// Adresse de courriel non définie ?
		if (!$contact['email'])
		{
			Report::info(__('Aucune adresse de courriel n\'a été définie.'));
			return 1;
		}

		// Si le formulaire n'a pas été envoyé, on arrête là.
		if (empty($_POST['send']))
		{
			return 1;
		}

		// Vérification par un faux champ de formulaire.
		if (!isset($_POST['f_email']) || $_POST['f_email'] !== '')
		{
			Report::warning('Bot detected.');
			return 1;
		}

		// Vérification de chaque champ.
		foreach (Mail::FIELDS_MAXLENGTH as $field => $maxlength)
		{
			// On vérifie que le champ a été rempli.
			if (!isset($_POST[$field]) || Utility::isEmpty($_POST[$field]))
			{
				Report::warning(L10N::getText('required_fields'));
				Template::set('field_error', $field);
				return 1;
			}

			// On vérifie la longueur du champ.
			$_POST[$field] = Utility::trimAll($_POST[$field]);
			if (mb_strlen($_POST[$field]) > $maxlength)
			{
				if ($field == 'message')
				{
					Report::warning(sprintf(L10N::getText('message_maxlength'), $maxlength));
					Template::set('field_error', $field);
				}
				return 1;
			}
		}

		// Vérification du format de l'adresse de courriel.
		if (($r = User::checkEmailFormat($_POST['email'])) !== TRUE)
		{
			Report::warning($r);
			Template::set('field_error', 'email');
			return 1;
		}

		// Vérification par listes noires.
		$r = App::blacklists('contact', $_POST['name'], $_POST['email'], $_POST['message'],
		[
			'name' => $_POST['name'],
			'email' => $_POST['email'],
			'subject' => $_POST['subject'],
			'message' => $_POST['message']
		]);
		if (is_array($r))
		{
			$field = '';
			if ($r['list'] == 'emails')
			{
				$field = 'email';
			}
			if ($r['list'] == 'names')
			{
				$field = 'name';
			}
			if ($r['list'] == 'words')
			{
				$field = 'message';
			}
			Report::warning($r['text']);
			Template::set('field_error', $field);
			return 1;
		}

		// Message du courriel.
		$gallery_url = GALLERY_HOST . App::getURLGallery();
		$message = $_POST['message'];
		$message .= "\n\n-- \n";
		$message .= sprintf(__('Ce message vous a été envoyé par '
			. 'le formulaire de contact de la galerie %s.'), $gallery_url) . "\n";
		$message .= sprintf(__('IP expéditeur : %s'), $_SERVER['REMOTE_ADDR']) . "\n";

		// Envoi du courriel.
		$mail = new Mail();
		$mail->messages[] =
		[
			'to' => $contact['email'],
			'from' => $_POST['email'],
			'name' => $_POST['name'],
			'subject' => $_POST['subject'],
			'message' => $message
		];
		if (!$mail->send())
		{
			return -1;
		}

		// Log d'activité.
		App::logActivity('contact', '',
		[
			'from' => $_POST['email'],
			'name' => $_POST['name'],
			'subject' => $_POST['subject'],
			'message' => $_POST['message']
		]);

		// Confirmation de l'envoi du message.
		App::redirect('contact/confirm');
		return 1;
	}

	/**
	 * Pages personnalisées.
	 *
	 * @return int
	 */
	public static function custom(): int
	{
		if (!isset(Config::$params['pages_params']['custom_' . $_GET['page_id']]))
		{
			return 0;
		}

		$params = Config::$params['pages_params']['custom_' . $_GET['page_id']];
		if (!$params['status'])
		{
			return 0;
		}

		$content = NULL;
		$filename = NULL;
		$f = (string) $params['filename'];
		if (isset($params['filename']) && preg_match(Pages::CUSTOM_FILE_REGEXP, $f)
		&& file_exists($f = GALLERY_ROOT . '/files/pages/' . $f))
		{
			$filename = $f;
		}
		else
		{
			$content = $params['content'];
		}

		Template::set('custom_page',
		[
			'title' => $params['title'],
			'content' => $content,
			'filename' => $filename
		]);

		return 1;
	}

	/**
	 * Historique de la galerie.
	 *
	 * @return int
	 */
	public static function history(): int
	{
		if (isset($_GET['filter']))
		{
			unset($_GET['filter']);
		}
		Template::set('history', []);

		// Paramètres GET.
		$_GET['params'][1] = (int) ($_GET['params'][1] ?? '1');
		$_GET['params'][2] = $_GET['params'][2] ?? 'date-published';

		// Permet d'améliorer les performances.
		$date_format = !in_array(CONF_DB_TYPE, ['mysql', 'sqlite']);

		// SQL.
		$sql_column_date = $_GET['params'][2] == 'date-published' ? 'item_pubdt' : 'item_crtdt';
		$sql_date_format = "DATE_FORMAT($sql_column_date, '%s')";
		$sql_item_where = "AND $sql_column_date LIKE :date";
		$params = ['date' => $_GET['params'][3] ?? ''];
		switch (strlen($_GET['params'][3] ?? ''))
		{
			case 7 :
				$sql_select = sprintf($sql_date_format, '%%d');
				$sql_where = sprintf("AND $sql_date_format = :date", '%%Y-%%m');
				if ($date_format)
				{
					$sql_item_where = sprintf("AND $sql_date_format = :date", '%%Y-%%m-%%d');
				}
				$current_date = L10N::dt('F Y', $_GET['params'][3]);
				break;

			case 4 :
				$sql_select = sprintf($sql_date_format, '%%m');
				$sql_where = sprintf("AND $sql_date_format = :date", '%%Y');
				if ($date_format)
				{
					$sql_item_where = sprintf("AND $sql_date_format = :date", '%%Y-%%m');
				}
				$current_date = $_GET['params'][3];
				break;

			default :
				$sql_select = sprintf($sql_date_format, '%%Y');
				$sql_where = "";
				if ($date_format)
				{
					$sql_item_where = sprintf("AND $sql_date_format = :date", '%%Y');
				}
				$current_date = '';
				$params = [];
		}

		// Récupération des informations de la catégorie.
		$category = self::_getCategoryInfos($_GET['params'][1], __('Historique de %s'));
		if (!is_array($category))
		{
			return $category;
		}
		$cat_id = $category['cat_id'];
		$params['path'] = $cat_id > 1
			? DB::likeEscape($category['cat_path']) . '/%'
			: '%';

		// Récupération des dates (années, mois ou jours).
		$sql_from_where = "
				  FROM {items} AS i
			 LEFT JOIN {categories} AS cat USING (cat_id)
				 WHERE item_status = '1'
				   AND item_path LIKE :path
				   AND %s
				   AND %s";
		$sql = "SELECT DISTINCT $sql_select AS date
				       $sql_from_where
				       $sql_where
			  ORDER BY date DESC";
		DB::params($params);
		if (!DB::execute(sprintf($sql, SQL::catPerms(), SQL::catPassword())))
		{
			return -1;
		}
		$dates = DB::fetchAll('date', 'date');

		$history = [];
		foreach ($dates as $date)
		{
			if (!$date)
			{
				continue;
			}

			// Paramètres communs des prochaines requêtes SQL.
			$item_params =
			[
				'date' =>
					(isset($params['date']) ? $params['date'] . '-' . $date : $date) .
					($date_format ? '' : '%'),
				'path' => $params['path']
			];

			// Nombre de fichiers correspondant à la date.
			$sql = "SELECT COUNT(*) AS count,
						   item_type
						   $sql_from_where
						   $sql_item_where
				  GROUP BY item_type";
			DB::params($item_params);
			if (!DB::execute(sprintf($sql, SQL::catPerms(), SQL::catPassword())))
			{
				return -1;
			}
			$count = Item::countByTypes(DB::fetchAll('item_type'));

			// Texte pour le nombre de fichiers.
			$count_text_images = $count['images'] > 1 ? __('%s photos') : __('%s photo');
			$count_text_images = sprintf($count_text_images, $count['images']);
			$count_text_videos = $count['videos'] > 1 ? __('%s vidéos') : __('%s vidéo');
			$count_text_videos = sprintf($count_text_videos, $count['videos']);
			$count_text = $count['images'] && $count['videos']
				? sprintf(__('%s et %s'), $count_text_images, $count_text_videos)
				: ($count['images'] ? $count_text_images : $count_text_videos);

			// Informations du fichier associé à la date.
			$sql = "SELECT item_id,
						   item_adddt,
						   item_width,
						   item_height,
						   item_type,
						   item_name,
						   item_path,
						   item_orientation
						   $sql_from_where
						   $sql_item_where
				  ORDER BY item_id ASC
					 LIMIT 1";
			DB::params($item_params);
			if (!DB::execute(sprintf($sql, SQL::catPerms(), SQL::catPassword())))
			{
				return -1;
			}
			$i = DB::fetchRow();

			// Données de template.
			if (isset($_GET['params'][3]))
			{
				$date = $_GET['params'][3] . '-' . $date;
			}
			switch (strlen($date))
			{
				case 10 :
					$h_date = L10N::dt('l j', $date);
					break;

				case 7 :
					$h_date = L10N::dt('F', $date);
					break;

				default :
					$h_date = $date;
			}
			$link_history = 'history/' . $cat_id . '/' . $_GET['params'][2] . '/' . $date;
			$history[$h_date] =
			[
				'count' => $count,
				'count_text' => $count_text,
				'link_history' => strlen($date) < 8
					? App::getURL($link_history)
					: NULL,
				'link_items' => App::getURL(
					str_replace('history', $category['cat_type'], $link_history)
				),
				'item' =>
				[
					'id' => $i['item_id'],
					'is_video' => Item::isVideo($i['item_type']) ? 'video' : 'image',
					'thumb_size' => function(int $max_width, int $max_height) use ($i): array
					{
						if (!$i['item_width'] || !$i['item_height'])
						{
							$i['item_width'] = 400;
							$i['item_height'] = 227;
						}
						return Image::getResizedSize((int) $i['item_width'],
							(int) $i['item_height'], $max_width, $max_height);
					},
					'thumb_src' => function($size = '', $quality = '') use ($i)
					{
						return htmlspecialchars(
							App::getThumbSource('item', $i, (string) $size, (string) $quality)
						);
					},
					'title' => $i['item_name']
				]
			];
		}

		Template::set('history', $history);
		Template::set('history_current_date', $current_date);
		Template::set('history_category', $cat_id > 1
			? $category['cat_name']
			: __('Galerie'));
		Template::set('history_link_created', App::getURL("history/$cat_id/date-created"));
		Template::set('history_link_published', App::getURL("history/$cat_id/date-published"));

		return 1;
	}

	/**
	 * Récupération des tags.
	 *
	 * @return int
	 */
	public static function tags(): int
	{
		Template::set('tags', []);

		// Récupération des informations de la catégorie.
		$cat_infos = self::_getCategoryInfos($_GET['tags_id'] ?? 1, __('Tags de %s'));
		if (!is_array($cat_infos))
		{
			return $cat_infos;
		}

		// Tags combinés.
		Template::set('breadcrumb_tags', []);
		if (count($_GET['params']) == 3)
		{
			$sql = sprintf(
				'SELECT * FROM {tags} WHERE tag_id IN (%s) ORDER BY tag_name ASC',
				DB::inInt(explode(', ', $_GET['params'][2]))
			);
			if (!DB::execute($sql))
			{
				return -1;
			}
			$tags = [];
			foreach (DB::fetchAll('tag_id') as &$t)
			{
				$tags[] =
				[
					'link' => App::getURL(
						'category/1/tag/' . $t['tag_id'] . '-' . $t['tag_url']
					),
					'name' => $t['tag_name']
				];
			}
			if (!$tags)
			{
				return 0;
			}
			Template::set('breadcrumb_tags', $tags);
		}

		// Récupération des tags.
		require_once(__DIR__ . '/GalleryCategory.class.php');
		$tags = GalleryCategory::getTags($cat_infos, -1);
		Template::set('tags', $tags);

		return 1;
	}

	/**
	 * Récupération des informations des fichiers
	 * et des catégories à géolocaliser.
	 *
	 * @return int
	 */
	public static function worldmap(): int
	{
		$worldmap = Config::$params['pages_params']['worldmap'];
		Template::set('worldmap',
		[
			'layer' => Config::$params['geolocation_default_layer'],
			'latitude' => $worldmap['center_lat'],
			'longitude' => $worldmap['center_long'],
			'zoom' => $worldmap['zoom']
		]);
		$coords = [];

		// Récupération des fichiers à géolocaliser.
		$sql = 'SELECT item_id,
					   item_type,
					   item_path,
					   item_url,
					   item_desc,
					   item_duration,
					   item_tb_params,
					   item_lat,
					   item_long,
					   item_name,
					   item_adddt,
					   item_orientation,
					   cat_url
				  FROM {items} AS i
			 LEFT JOIN {categories} AS cat USING (cat_id)
				 WHERE item_status = "1"
				   AND item_lat IS NOT NULL
				   AND item_long IS NOT NULL
				   AND ' . SQL::catPerms() . '
				   AND ' . SQL::catPassword();
		if (!DB::execute($sql))
		{
			return -1;
		}
		if ($items = DB::fetchAll())
		{
			foreach ($items as &$i)
			{
				if (!isset($coords[$i['item_lat'] . ' ' . $i['item_long']]))
				{
					$coords[$i['item_lat'] . ' ' . $i['item_long']] =
					[
						'categories' => [],
						'items' => [],
						'lat' => $i['item_lat'],
						'long' => $i['item_long']
					];
				}
				$coords[$i['item_lat'] . ' ' . $i['item_long']]['items'][] =
				[
					'duration' => $i['item_duration']
						? App::formatDuration($i['item_duration'])
						: NULL,
					'id' => $i['item_id'],
					'link' => App::getURL('item/' . $i['item_id'] . '-' . $i['item_url']),
					'thumb_src' => function($size = '', $quality = '') use ($i)
					{
						return htmlspecialchars(
							App::getThumbSource('item', $i, (string) $size, (string) $quality)
						);
					},
					'title' => $i['item_name'],
					'type' => Item::isImage($i['item_type']) ? 'image' : 'video'
				];
			}
		}

		// Récupération des catégories à géolocaliser.
		$sql = 'SELECT cat.cat_id,
					   thumb_id,
					   cat_path,
					   cat_name,
					   cat_desc,
					   cat_url,
					   cat_lat,
					   cat_long,
					   cat_tb_params,
					   cat_crtdt,
					   cat_filemtime,
					   CASE WHEN cat_filemtime IS NULL
						    THEN "category" ELSE "album"
							 END AS cat_type,
					   item_id,
					   item_path,
					   item_type,
					   item_width,
					   item_height,
					   item_orientation,
					   item_adddt
				  FROM {categories} AS cat
			 LEFT JOIN {items} AS i
					ON cat.thumb_id = i.item_id
				 WHERE cat_status = "1"
				   AND cat_lat IS NOT NULL
				   AND cat_long IS NOT NULL
				   AND ' . SQL::catPerms() . '
				   AND ' . SQL::catPassword();
		if (!DB::execute($sql))
		{
			return -1;
		}
		if ($categories = DB::fetchAll())
		{
			foreach ($categories as &$i)
			{
				if (!isset($coords[$i['cat_lat'] . ' ' . $i['cat_long']]))
				{
					$coords[$i['cat_lat'] . ' ' . $i['cat_long']] =
					[
						'categories' => [],
						'items' => [],
						'lat' => $i['cat_lat'],
						'long' => $i['cat_long']
					];
				}
				$coords[$i['cat_lat'] . ' ' . $i['cat_long']]['categories'][] =
				[
					'id' => $i['thumb_id'] > 0 ? $i['item_id'] : $i['cat_id'],
					'link' => App::getURL(
						$i['cat_type'] . '/' . $i['cat_id'] . '-' . $i['cat_url']
					),
					'thumb_src' => function($size = '', $quality = '') use ($i)
					{
						return htmlspecialchars(
							App::getThumbSource('cat', $i, (string) $size, (string) $quality)
						);
					},
					'title' => $i['cat_name']
				];
			}
		}

		Template::set('coords', array_values($coords));

		return 1;
	}



	/**
	 * Récupération des informations de la catégorie.
	 *
	 * @param int $cat_id
	 * @param string $breadcrumb_text
	 *
	 * @return mixed
	 */
	private static function _getCategoryInfos(int $cat_id, string $breadcrumb_text)
	{
		$sql = 'SELECT cat.*,
					   ' . SQL::catPassword('select') . ',
					   CASE WHEN cat_filemtime IS NULL
						    THEN "category" ELSE "album"
							 END AS cat_type
				  FROM {categories} AS cat
				 WHERE cat.cat_id = :cat_id
				   AND cat_status = "1"
				   AND ' . SQL::catPerms();
		DB::params(['cat_id' => $cat_id]);
		if (!DB::execute($sql))
		{
			return -1;
		}
		if (!$cat_infos = DB::fetchRow())
		{
			return 0;
		}

		// L'utilisateur a-t-il entré le bon mot de passe ?
		if (!self::checkCookiePassword($cat_infos))
		{
			return 0;
		}

		// Réduction des stats.
		if (!self::changeCatStats($cat_infos))
		{
			return -1;
		}

		// Fil d'Ariane.
		$breadcrumb =
		[
			'category_link' => App::getURL(),
			'category_name' => __('la galerie'),
			'category_text' => '%s',
			'text' => $breadcrumb_text
		];
		if ($cat_infos['cat_id'] > 1)
		{
			$breadcrumb['category_link'] = App::getURL(
				$cat_infos['cat_type'] . '/' . $cat_infos['cat_id'] . '-' . $cat_infos['cat_url']
			);
			$breadcrumb['category_name'] = $cat_infos['cat_name'];
			$breadcrumb['category_text'] = $cat_infos['cat_type'] == 'category'
				? __('la catégorie %s')
				: __('l\'album %s');
		}
		Template::set('breadcrumb', $breadcrumb);

		return $cat_infos;
	}
}
?>