<?php (defined('BASEPATH')) OR exit('No direct script access allowed');

/**
 * Modular Extensions - HMVC
 * Adapted from wiredesignz codeigniter-modular-extensions-hmvc 5.5
 */
#[\AllowDynamicProperties]
class MX_Router extends CI_Router
{
	private $module;
	private $located = 0;

	public function fetch_module()
	{
		return $this->module;
	}

	protected function _set_request($segments = array())
	{
		$segments = $this->locate($segments);

		if ($this->located == -1)
		{
			$this->_set_404override_controller();
			return;
		}

		if (empty($segments))
		{
			$this->_set_default_controller();
			return;
		}

		$this->set_class($segments[0]);

		if (isset($segments[1]))
		{
			$this->set_method($segments[1]);
		}
		else
		{
			$segments[1] = 'index';
		}

		array_unshift($segments, NULL);
		unset($segments[0]);
		$this->uri->rsegments = $segments;
	}

	/** 404 override **/
	protected function _set_404override_controller()
	{
		$this->directory = '';
		$_404 = explode('/', $this->routes['404_override']);

		if ($located = $this->locate($_404))
		{
			$this->located = 0;
			$this->_set_request($located);
		}
	}

	/** Set the default controller **/
	protected function _set_default_controller()
	{
		if (empty($this->directory))
		{
			/* set the default controller module path */
			$this->_set_module_path($this->default_controller);
		}

		if (strpos($this->default_controller, '/') !== FALSE)
		{
			$segments = explode('/', $this->default_controller);
			$this->set_class($segments[0]);
			$this->set_method($segments[1]);
			$this->_set_request($segments);
		}
		else
		{
			$this->set_class($this->default_controller);
			$this->set_method('index');
			$this->_set_request(array($this->default_controller, 'index'));
		}

		log_message('debug', 'No URI present. Default controller set.');
	}

	/** Locate the controller **/
	public function locate($segments)
	{
		$this->located = 0;
		$ext = EXT;

		/* use module route if available */
		if (isset($segments[0]) AND $routes = Modules::parse_routes($segments[0], implode('/', $segments)))
		{
			$segments = $routes;
		}

		/* get the segments array elements */
		list($module, $directory, $controller) = array_pad($segments, 3, NULL);

		/* check modules */
		foreach (Modules::$locations as $location => $offset)
		{
			/* module exists? */
			if (is_dir($source = $location.$module.'/controllers/'))
			{
				$this->module = $module;
				$this->directory = $offset.$module.'/controllers/';

				/* module sub-controller exists? */
				if ($directory AND is_file($source.ucfirst($directory).$ext))
				{
					$this->class = $directory;
					return array_slice($segments, 1);
				}

				/* module sub-directory exists? */
				if ($directory AND is_dir($source.$directory.'/'))
				{
					$source = $source.$directory.'/';
					$this->directory .= $directory.'/';

					/* module sub-directory controller exists? */
					if (is_file($source.ucfirst($directory).$ext))
					{
						return array_slice($segments, 1);
					}

					/* module sub-directory sub-controller exists? */
					if ($controller AND is_file($source.ucfirst($controller).$ext))
					{
						return array_slice($segments, 2);
					}
				}

				/* module controller exists? */
				if (is_file($source.ucfirst($module).$ext))
				{
					return $segments;
				}

				/* get default controller */
				if ($directory AND is_file($source.ucfirst($directory).$ext))
				{
					$this->class = $directory;
					return array_slice($segments, 1);
				}
			}
		}

		/* application controller exists? */
		if (is_file(APPPATH.'controllers/'.ucfirst($module).$ext))
		{
			return $segments;
		}

		/* application sub-directory controller exists? */
		if ($directory AND is_file(APPPATH.'controllers/'.$module.'/'.ucfirst($directory).$ext))
		{
			$this->directory = $module.'/';
			return array_slice($segments, 1);
		}

		/* application sub-directory default controller exists? */
		if ($module AND is_dir(APPPATH.'controllers/'.$module.'/'))
		{
			$this->directory = $module.'/';
			return $segments;
		}

		/* application default controller in sub-directory? */
		if ($module AND is_file(APPPATH.'controllers/'.$module.'/'.ucfirst($this->default_controller).$ext))
		{
			$this->directory = $module.'/';
			return array($this->default_controller);
		}

		$this->located = -1;
		return $segments;
	}

	/** Set the module path **/
	protected function _set_module_path(&$_route)
	{
		if ( ! empty($_route))
		{
			/* check modules */
			foreach (Modules::$locations as $location => $offset)
			{
				/* module exists? */
				if (is_dir($source = $location.strtolower($_route).'/controllers/'))
				{
					$this->module = strtolower($_route);
					$this->directory = $offset.strtolower($_route).'/controllers/';

					/* module sub-controller exists? */
					if (is_file($source.ucfirst($_route).EXT))
					{
						return $_route;
					}
				}
			}
		}
	}
}
