<?php
/**
 * @version        4.3.0
 * @package        Joomla
 * @subpackage     Helpdesk Pro
 * @author         Tuan Pham Ngoc
 * @copyright      Copyright (C) 2013 - 2021 Ossolution Team
 * @license        GNU/GPL, see LICENSE.php
 */

namespace OSSolution\HelpdeskPro\Site\Helper;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Multilanguage;

defined('_JEXEC') or die;

class Route
{
	/**
	 * Cached categories
	 *
	 * @var array
	 */
	protected static $categories;

	/**
	 * Cached articles, which can be passed from outside to reduce number of queries
	 *
	 * @var array
	 */
	protected static $articles = [];

	/**
	 * Store menu items created to link to the component
	 *
	 * @var array
	 */
	protected static $lookup;

	/**
	 * Function to get Tickets Route
	 *
	 * @param   string  $language
	 *
	 * @return string
	 */
	public static function getTicketsRoute($language = '*')
	{
		$link = 'index.php?option=com_helpdeskpro&view=tickets';

		$needles = [
			'tickets' => [0],
		];

		if ($language != "*" && Multilanguage::isEnabled())
		{
			$link                .= '&lang=' . $language;
			$needles['language'] = $language;
		}

		if ($item = self::findItem($needles))
		{
			$link .= '?Itemid=' . $item;
		}

		return $link;
	}

	/**
	 * Function to get Ticket Route
	 *
	 * @param   mixed   $id  Ticket ID or Ticket Code, depends on $isId parameter
	 * @param   bool    $isId
	 * @param   string  $language
	 *
	 * @return string
	 */
	public static function getTicketRoute($id, $isId = true, $language = '*')
	{
		$link = 'index.php?option=com_helpdeskpro&view=ticket';

		if ($isId)
		{
			$link .= '&id=' . $id;
		}
		else
		{
			$link .= '&ticket_code=' . $id;
		}

		if ($language != "*" && Multilanguage::isEnabled())
		{
			$link .= '&lang=' . $language;
		}

		if ($isId)
		{
			if ($item = self::findItem(['tickets' => [0], 'language' => $language]))
			{
				$link .= '&Itemid=' . $item;
			}
			elseif ($item = self::findItem(['ticket' => [0], 'language' => $language]))
			{
				$link .= '&layout=default&Itemid=' . $item;
			}
		}
		else
		{
			if ($item = self::findItem(['ticket' => [0], 'language' => $language]))
			{
				$link .= '&layout=default&Itemid=' . $item;
			}
		}

		return $link;
	}

	/**
	 * Method to get articles route (display articles from a category)
	 *
	 * @param           $id
	 * @param   int     $itemId
	 * @param   string  $language
	 */
	public static function getArticlesRoute($id, $itemId = 0, $language = '*')
	{
		$link = 'index.php?option=com_helpdeskpro&view=articles&id=' . $id;

		$needles = ['articles' => [$id]];

		if ($language != "*" && Multilanguage::isEnabled())
		{
			$needles['language'] = $language;
			$link                .= '&lang=' . $language;
		}

		if ($item = self::findItem($needles, $itemId))
		{
			$link .= '&Itemid=' . $item;
		}

		return $link;
	}

	/**
	 * @param   int     $id
	 * @param   int     $catId
	 * @param   int     $itemId
	 * @param   string  $language
	 */
	public static function getArticleRoute($id, $catId, $itemId = 0, $language = '*')
	{
		$id      = (int) $id;
		$needles = ['article' => [$id]];
		$link    = 'index.php?option=com_helpdeskpro&view=article&id=' . $id;

		if (!$catId)
		{
			//Find the main category of this event
			$db    = Factory::getDbo();
			$query = $db->getQuery(true)
				->select('category_id')
				->from('#__helpdeskpro_articles')
				->where('id = ' . $id);
			$db->setQuery($query);
			$catId = (int) $db->loadResult();
		}

		if ($catId)
		{
			$needles['articles'] = self::getCategoriesPath($catId, 'id', false);
			$link                .= '&catid=' . $catId;
		}

		$needles['categories'] = [0];

		if ($language != "*" && Multilanguage::isEnabled())
		{
			$link .= '&lang=' . $language;

			$needles['language'] = $language;
		}

		if ($item = self::findItem($needles, $itemId))
		{
			$link .= '&Itemid=' . $item;
		}

		return $link;
	}

	/**
	 * Get path to the category
	 *
	 * @param   int     $id
	 * @param   string  $type
	 * @param   bool    $reverse
	 *
	 * @return array
	 */
	public static function getCategoriesPath($id, $type = 'id', $reverse = true)
	{
		self::getCategories();;

		$paths = [];

		if ($type == 'id')
		{
			do
			{
				$paths[] = self::$categories[$id]->{$type};
				$id      = self::$categories[$id]->parent_id;
			} while ($id != 0);

			if ($reverse)
			{
				$paths = array_reverse($paths);
			}
		}
		else
		{
			$paths[] = self::$categories[$id]->{$type};
		}

		return $paths;
	}

	/**
	 * Find item id variable corresponding to the view
	 *
	 * @param   string  $view
	 * @param   int     $itemId
	 * @param   string  $language
	 *
	 * @return int
	 */
	public static function findView($view, $itemId, $language = '*')
	{
		$needles = [
			$view => [0],
		];

		if ($language != "*" && Multilanguage::isEnabled())
		{
			$needles['language'] = $language;
		}

		if ($item = self::findItem($needles, $itemId))
		{
			return $item;
		}

		return 0;
	}

	/**
	 *
	 * Function to find Itemid
	 *
	 * @param   string  $needles
	 * @param   int     $itemId
	 *
	 * @return int
	 */
	public static function findItem($needles = null, $itemId = 0)
	{
		$app      = Factory::getApplication();
		$menus    = $app->getMenu('site');
		$language = isset($needles['language']) ? $needles['language'] : '*';

		// Prepare the reverse lookup array.
		if (!isset(self::$lookup[$language]))
		{
			self::$lookup[$language] = array();

			$component = ComponentHelper::getComponent('com_helpdeskpro');

			$attributes = array('component_id');
			$values     = array($component->id);

			if ($language != '*')
			{
				$attributes[] = 'language';
				$values[]     = array($needles['language'], '*');
			}

			$items = $menus->getItems($attributes, $values);

			foreach ($items as $item)
			{
				if (isset($item->query) && isset($item->query['view']))
				{
					$view = $item->query['view'];

					if (!isset(self::$lookup[$language][$view]))
					{
						self::$lookup[$language][$view] = array();
					}

					if (isset($item->query['id']) || $item->query['filter_category_id'])
					{
						$id = isset($item->query['id']) ? $item->query['id'] : $item->query['filter_category_id'];

						/**
						 * Here it will become a bit tricky
						 * language != * can override existing entries
						 * language == * cannot override existing entries
						 */
						if (!isset(self::$lookup[$language][$view][$id]) || $item->language != '*')
						{
							self::$lookup[$language][$view][$id] = $item->id;
						}
					}
				}
			}
		}

		if ($needles)
		{
			foreach ($needles as $view => $ids)
			{
				if (isset(self::$lookup[$language][$view]))
				{
					foreach ($ids as $id)
					{
						if (isset(self::$lookup[$language][$view][(int) $id]))
						{
							return self::$lookup[$language][$view][(int) $id];
						}
					}
				}
			}
		}

		//Return default item id
		return $itemId;
	}

	/**
	 * Get categories
	 *
	 * @return void
	 */
	protected static function getCategories()
	{
		$db    = Factory::getDbo();
		$query = $db->getQuery(true)
			->select('id, parent_id')->from('#__helpdeskpro_categories')
			->where('published = 1');

		if ($fieldSuffix = Helper::getFieldSuffix())
		{
			$aliasField = $db->quoteName('alias' . $fieldSuffix);
			$query->select("IF(CHAR_LENGTH($aliasField) > 0, $aliasField, alias) AS alias");
		}
		else
		{
			$query->select('alias');
		}

		$db->setQuery($query);

		self::$categories = $db->loadObjectList('id');
	}

	/**
	 * Add articles to cached articles
	 *
	 * @param   array  $articles
	 */
	public static function addArticles($articles)
	{
		foreach ($articles as $article)
		{
			self::$articles[$article->id] = $article;
		}
	}

	/**
	 * Get alias of category
	 *
	 * @param   int  $id
	 *
	 * @return string
	 */
	public static function getCategoryAlias($id)
	{
		self::getCategories();

		return self::$categories[$id]->alias;
	}

	/**
	 * Method to get article alias
	 *
	 * @param   int  $id
	 *
	 * @return string
	 */
	public static function getArticleAlias($id)
	{
		if (isset(self::$articles[$id]))
		{
			$db = Factory::getDbo();

			$query = $db->getQuery(true)
				->select('id')->from('#__helpdeskpro_articles')
				->where('id = ' . $id);

			if ($fieldSuffix = Helper::getFieldSuffix())
			{
				$aliasField = $db->quoteName('alias' . $fieldSuffix);
				$query->select("IF(CHAR_LENGTH($aliasField) > 0, $aliasField, alias) AS alias");
			}
			else
			{
				$query->select('alias');
			}

			$db->setQuery($query);

			self::$articles[$id] = $db->loadObject();
		}

		return self::$articles[$id]->alias;
	}
}