<?php

/**
 * vB_Api_Route
 *
 * @package vBApi
 * @access public
 */
class vB_Api_Route extends vB_Api
{

	protected function __construct()
	{
		parent::__construct();
	}

	/**
	 * Returns the array of routes for the application
	 *
	 * @return 	array	The routes
	 */
	public function fetchAll()
	{
		$result = vB::getDbAssertor()->assertQuery(
			'routenew',
			array(
				vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT,
			)
		);

		$routes = array();
		if ($result->valid())
		{
			foreach ($result AS $route)
			{
				if (($unserialized = @unserialize($route['arguments'])) !== false)
				{
					$route['arguments'] = $unserialized;
				}
				else
				{
					$route['arguments'] = array();
				}
				$routes[$route['routeid']] = $route;
			}
		}

		//uasort($routes, array($this, '_sortRoutes'));

		return $routes;
	}

	/**
	 * Returns a matching route if available for $pathInfo
	 *
	 * @param string $pathInfo
	 * @param string $queryString
	 * @return vB_Frontend_Route
	 */
	public function getRoute($pathInfo, $queryString)
	{
		// clean the path if necessary
		$parsed = parse_url($pathInfo);
		$pathInfo = $parsed['path'];

		// check for any querystring to append
		if (!empty($parsed['query']) AND !empty($queryString))
		{
			$queryString = $parsed['query'] . $queryString;
		}

		// calculate prefixes set
		$prefixes = vB5_Route::getPrefixSet($pathInfo);

		// get matching routes
		$result = vB::getDbAssertor()->getRows('routenew', array('prefix' => $prefixes));
		$prefixMatches = array();
		if ($result)
		{
			foreach ($result AS $route)
			{
				if (($unserialized = @unserialize($route['arguments'])) !== false)
				{
					$route['arguments'] = $unserialized;
				}
				else
				{
					$route['arguments'] = array();
				}
				$prefixMatches[$route['routeid']] = $route;
			}
		}

		// get best route
		try 
		{
			$route = vB5_Route::selectBestRoute($pathInfo, $queryString, $prefixMatches);
		}
		catch (vB_Exception_Api $ex)
		{
			$route = array(
				'internal_error' => $ex
			);
		}
		catch (vB_Exception_NodePermission $ex)
		{
			$route = array(
				'no_permission'	=> 1
			);
		}

		if ($route)
		{
			// check for banned
			$bannedInfo = vB_Library::instance('user')->fetchBannedInfo(false);
			if ($bannedInfo['isbanned'])
			{
				return array('banned_info' => $bannedInfo);
			}
			else if (is_array($route) AND (isset($route['no_permission']) OR isset($route['internal_error'])))
			{
				return $route;
			}
			
			$canonicalUrl = $route->getCanonicalUrl();
			$canonicalPathInfo = ($canonicalUrl) ? parse_url($canonicalUrl, PHP_URL_PATH) : $pathInfo;
			if ($canonicalPathInfo AND $canonicalPathInfo{0} == '/')
			{
				$canonicalPathInfo = substr($canonicalPathInfo, 1);
			}

			if ($redirectId = $route->getRedirect301())
			{
				return array(
					'redirect'	=> vB5_Route::buildUrl($redirectId, $route->getArguments(), $route->getQueryParameters()),
					'redirectRouteId' => $redirectId
				);
			}
			else if ($pathInfo != $canonicalPathInfo)
			{
				return array(
					'redirect' => $canonicalUrl . (empty($queryString) ? '' : "?$queryString"),
					'redirectRouteId' => $route->getRouteId()
				);
			}
			else
			{
				return array(
					'routeid'         => $route->getRouteId(),
					'routeguid'       => $route->getRouteGuid(),
					'controller'      => $route->getController(),
					'action'          => $route->getAction(),
					'template'        => $route->getTemplate(),
					'arguments'       => $route->getArguments(),
					'queryParameters' => $route->getQueryParameters(),
					'pageKey'         => $route->getPageKey(),
					'userAction'      => $route->getUserAction(),
					'breadcrumbs'     => $route->getBreadcrumbs(),
				);
			}
		}
		else
		{
			return false;
		}
	}

	/**
	 * Returns the route id for the generic conversation route
	 * @param int $channelId
	 * @return int
	 */
	public function getChannelConversationRoute($channelId)
	{
		if(empty($channelId))
		{
			return false;
		}

		$route = vB::getDbAssertor()->getRow('routenew', array('class'=>'vB5_Route_Conversation', 'contentid'=>intval($channelId)));

		if(empty($route))
		{
			return false;
		}

		return $route['routeid'];
	}

	/**
	 *
	 * @param mixed $route
	 * @param array $data
	 * @param array $extra
	 * @return string
	 */
	public function getUrl($route, array $data, array $extra)
	{
		return vB5_Route::buildUrl($route, $data, $extra);
	}

	/**
	 * Saves a new route
	 *
	 * @param	string	Route class name
	 * @param	array	Route data
	 *(
	 * @return	mixed	The routeid will be returned
	 */
	public function createRoute($class, array $data)
	{
		return call_user_func(array($class, 'createRoute'), $class, $data);
	}

	/**
	 * Updates an existing route
	 *
	 * @param	mixed	Route id
	 * @param	array	Route data
	 *
	 * @return	mixed	The routeid will be returned
	 */
	public function updateRoute($routeId, array $data)
	{
		return vB5_Route::updateRoute($routeId, $data);
	}

	public function updateNewPageRoute($pageId, $routeId)
	{
		$db = vB::getDbAssertor();

		$db->update('page', array('routeid'=>$routeId), array('pageid'=>$pageId));

		$pageRoute = $db->getRow('routenew', array(
			vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT,
			vB_dB_Query::CONDITIONS_KEY => array(
				'routeid' => $routeId
			)
		));

		// update routes for included channels
		$pageWidgets = $db->getRows('getPageWidgetsByType', array(
			vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED,
			'pageid'	=> $pageId,
			'widgetids'	=> 3 // TODO: replace with a class constant
		));

		if ($pageWidgets)
		{
			$channelIds = array();
			foreach ($pageWidgets AS $widget)
			{
				$adminConfig = unserialize($widget['adminconfig']);
				if (isset($adminConfig['channel_node_ids']))
				{
					$channelIds = array_merge($channelIds, $adminConfig['channel_node_ids']);
				}
			}

			if ($channelIds)
			{
				$routes = $db->getRows('getChannelRoutes', array(
					vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED,
					'channelids'	=> $channelIds
				));

				$defaultPrefix = 'home';
				foreach ($routes AS $route)
				{
					if (strpos($route['prefix'], $defaultPrefix) === 0)
					{
						$newprefix = preg_replace("#^$defaultPrefix#", $pageRoute['prefix'], $route['prefix']);
						$newregex = preg_replace("#^$defaultPrefix#", $pageRoute['prefix'], $route['regex']);

						$db->update('routenew', array('prefix'=>$newprefix, 'regex'=>$newregex), array('routeid'=>$route['routeid']));
					}
				}
			}
		}
	}

	/**
	 * Writes debugging output to the filesystem for AJAX calls
	 *
	 * @param	mixed	Output to write
	 */
	protected function _writeDebugOutput($output)
	{
		$fname = dirname(__FILE__) . '/_debug_output.txt';
		file_put_contents($fname, $output);
	}
}
