<?php

/**
 * @author arson
 */
abstract class Eppe_Module_ModuleAbstract implements Eppe_Module_ModuleInterface {

	/**
	 * @var array Instancje poszczególnych modułów
	 */
	static $instances = array();

	/**
	 * @return Eppe_Module_ModuleAbstract Singleton modułu
	 */
	final public static function getInstance() {
		$calledClass = get_called_class();

		if( !array_key_exists($calledClass, self::$instances) ) {
			self::$instances[$calledClass] = new $calledClass;
		}

		return self::$instances[$calledClass];
	}

	/**
	 * @return array Lista modułów włączonych w application.ini
	 */
	static function getEnabledModules() {
		return Rtn_Application::$config->resources->modules->toArray();
	}

	/**
	 * @return array Tablica instancji modułów włączonych w application.ini
	 */
	static function getEnabledModulesInstances() {
		$instances = array();

		$modules = Eppe_Module_ModuleAbstract::getEnabledModules();
		foreach( $modules as $module ) {
			// nazwa klasy modułu
			$moduleClassName = ucfirst($module) . '_Module_Module';
			// dodanie do tablicy instancji
			$instances[$module] = $moduleClassName::getInstance();
		}

		return $instances;
	}

	/**
	 *
	 * @param type $module
	 * @return Eppe_Module_ModuleAbstract
	 */
	final static function getModuleInstance($module) {
		$instances = static::getEnabledModulesInstances();
		return $instances[$module];
	}

	/**
	 * @var string Nazwa modułu wyświetlana
	 */
	public $title;

	/**
	 * @var string Nazwa modułu maszynowa - jedno słowo. Ustalana automatycznie na podstawie nazwy klasy modułu.
	 */
	public $name;

	/**
	 * @var Zend_Config_Ini Konfiguracja modułu
	 */
	public $config;

	/**
	 * @var Eppe_Module_AclAbstract Uprawnienia modułu
	 */
	public $acl;

	/**
	 * @var Eppe_Module_MenuAbstract Menu modułu
	 */
	public $menu;

	public function __construct() {
		$this->_determineModuleName();
		$this->_prepareConfig();
		$this->_prepareTitle();
		$this->_aggregateSubClasses();
		$this->_initViewHelpers();
	}

	protected function _initViewHelpers() {
		$path = $this->getModulePath() . '/classes/View/Helper';
		$path_admin = $this->getModulePath() . '/classes/View/Helper/Admin';

		$view = Zend_Layout::startMvc()->getView();

		$view->addHelperPath($path, $this->name . '_View_Helper');
		$view->addHelperPath($path_admin, $this->name . '_View_Helper_Admin');
	}

	/**
	 * Ustalenie nazwy modułu
	 */
	protected function _determineModuleName() {
		$this->name = current(explode('_', get_class($this)));
	}

	/**
	 * Odczytuje konfiguracja modułu
	 */
	protected function _prepareConfig() {
		$appFilename = MODULES_PATH . $this->name . '/configs/module.ini';
		if( file_exists($appFilename) ) {
			$filename = $appFilename;
		}
		else {
			$filename = LIBRARY_PATH . 'Main/' . $this->name . '/configs/module.ini';
		}

		if( file_exists($filename) ) {
			$this->config = new Zend_Config_Ini($filename, 'development');
		}
		else {
			throw new Rtn_Exception_Module(__('File `module.ini` must exist in module `:module`', array( ':module' => $this->name )));
		}
	}

	/**
	 * Przenosi pełną nazwę modułu do składowej title
	 */
	protected function _prepareTitle() {
		$this->title = $this->config->title;
	}

	/**
	 * Agregacja klas składowych modułu
	 */
	protected function _aggregateSubClasses() {
		$aclClassName = $this->name . '_Module_Acl';
		$menuClassName = $this->name . '_Module_Menu';

		$this->acl = new $aclClassName;
		$this->menu = new $menuClassName;

		// Pomocnicze atrybuty agregowanych klas - możnaby to zmienić w taki sposób, żeby klasy agregowane miały atrybut z referencją do klasy modułu - do sprawdzenia/przemyślenia
		$this->acl->setModuleName($this->name);
		$this->menu->setModuleTitle($this->title);

		$this->acl->init();
	}

	/**
	 * @deprecated deprecated since RTN version
	 */
	public function getSiteJSPath() {
		return $this->getFrontJSPath();
	}

	/**
	 * @deprecated deprecated since RTN version
	 */
	public function getSiteCSSPath() {
		return $this->getFrontCSSPath();
	}

	/**
	 * @deprecated deprecated since RTN version
	 */
	public function getSiteImgPath() {
		return $this->getFrontImgPath();
	}

	/**
	 * Metoda zwraca ścieżkę do plików css admina danego modułu
	 */
	public function getAdminCSSPath() {
		return '/modules/' . $this->name . '/admin/css/';
	}

	/**
	 * Metoda zwraca ścieżkę do plików admina javascript danego modułu
	 */
	public function getAdminJSPath() {
		return '/modules/' . $this->name . '/admin/js/';
	}

	/**
	 * Metoda zwraca ścieżkę do plików obrazków admina danego modułu
	 */
	public function getAdminImgPath() {
		return '/modules/' . $this->name . '/admin/images/';
	}

	/**
	 * Metoda zwraca ścieżkę do plików fontface admina danego modułu
	 */
	public function getAdminFontfacePath() {
		return '/modules/' . $this->name . '/admin/fontface/';
	}

	/**
	 * Metoda zwraca ścieżkę do plików css danego modułu
	 */
	public function getFrontCSSPath() {
		return '/modules/' . $this->name . '/front/css/';
	}

	/**
	 * Metoda zwraca ścieżkę do plików javascript danego modułu
	 */
	public function getFrontJSPath() {
		return '/modules/' . $this->name . '/front/js/';
	}

	/**
	 * Metoda zwraca ścieżkę do plików obrazków danego modułu
	 */
	public function getFrontImgPath() {
		return '/modules/' . $this->name . '/front/images/';
	}
	
	/**
	 * Metoda zwraca ścieżkę do plików danego modułu
	 */
	public function getFrontFilesPath() {
		return '/modules/' . $this->name . '/front/files/';
	}

	/**
	 * Metoda zwraca ścieżkę do zasobów danego modułu
	 */
	public function getResourcesPath() {
		return $this->getModulePath() . '/resources/';
	}

	/**
	 * @return string Ścieżka do widoków modułu
	 */
	public function getViewsPath() {
		return $this->getModulePath() . '/views/';
	}

	/**
	 * @return string Ścieżka główna do modułu
	 */
	public function getModulePath() {
		return MODULES_PATH . $this->name;
	}

}
