<?php
/**
 * @package aowp.aspect
 * 
 */

/**
 * ユーザが定義したアスペクトのパス情報を管理し、指定した名前のアスペクトの定義ファイルのinclude処理を行います。
 * アスペクトのパス情報は、織り込み時に設定され、serialize関数を用いて保存されます。
 * 実行時には、unserialize関数を用いて、織り込み時に作成したインスタンスを利用します。
 *
 * @package aowp.aspect
 */
class AOWP_AspectManager {
	
	const SERIALIZATION_FILE_NAME = 'AOWP_AspectManager';
	const ASPECT_DEFINITION_FILE_PATERN = '/\.aspect\.php$/';
	const WEAVER_GENERATE_ASPECT_FOLDER = 'aspects';
	private $_aspectFileMap = array();
	private $_weaverGenerateAspectFileMap = array();
	
	private static function _getSerializationLocation() {
		return AOWP_ConfigurationManager::getCacheFolder() . AOWP_AspectManager::SERIALIZATION_FILE_NAME;
	}
	
	private static function _getWeaverGenerateAspectFolderPath() {
		return AOWP_ConfigurationManager::getCacheFolder() . AOWP_AspectManager::WEAVER_GENERATE_ASPECT_FOLDER . DIRECTORY_SEPARATOR;
	}
	
	public static function clearCache() {
		AOWP_AspectManager::_serialize(new AOWP_AspectManager());
	}

	public static function loadUserDefineAspect() {
		$aspectManager = new AOWP_AspectManager();
		$phpScriptFilePathArray = AOWP_PHPFileManager::getAllPHPFile(AOWP_ConfigurationManager::getRuntimeAspectFolder(), '/Aspect\.class\.php$/');
		foreach ($phpScriptFilePathArray as $phpScriptFilePath) {
			$aspectManager->addAspectFilePath(AOWP_AspectManager::_getAspectName($phpScriptFilePath), AOWP_AspectManager::_getRelativePathFromAspectFolder($phpScriptFilePath));
		}
		AOWP_AspectManager::_serialize($aspectManager);
	}
	private static function _getRelativePathFromAspectFolder($fullAspectPath) {
		return substr($fullAspectPath, strlen(AOWP_ConfigurationManager::getRuntimeAspectFolder() . DIRECTORY_SEPARATOR));
	}
	private static function _serialize($aspectManager) {
		AOWP_Logger::logging('Serialize AspectManager: ' . AOWP_AspectManager::_getSerializationLocation());
		AOWP_PHPFileManager::saveFile(AOWP_AspectManager::_getSerializationLocation(), serialize($aspectManager));
	}
	private static function _getAspectName($filePath) {
		$pathInfomation = pathinfo($filePath);
		$fileName = $pathInfomation['basename'];
		$fileNameArray = explode('.', $fileName);
		return $fileNameArray[0];
	}
	
	public function addAspectFilePath($aspectName, $aspectFilePath) {
		$this->_aspectFileMap[$aspectName] = $aspectFilePath;
	}
	
	public function addWeaverGenerateAspectFilePath($aspectName, $aspectFilePath) {
		$this->_weaverGenerateAspectFileMap[$aspectName] = $aspectFilePath;
	}
	
	private function _getAspectFilePath($aspectName) {
		if (array_key_exists($aspectName, $this->_aspectFileMap)) {
			return AOWP_ConfigurationManager::getRuntimeAspectFolder() . $this->_aspectFileMap[$aspectName];
		}
		else {
			return null;
		}
	}

	public static function getAspectFilePathAtWeaving($aspectName) {
		$aspectManager = AOWP_AspectManager::getInstance();
		return AOWP_ConfigurationManager::getRuntimeAspectFolder() . DIRECTORY_SEPARATOR . $aspectManager->_aspectFileMap[$aspectName];
	}
	
	public function getAspectFileMap() {
		return $this->_aspectFileMap;
	}
	
	
	public static function includeOnceAspect($aspectName) {
		$aspectManager = AOWP_AspectManager::getInstance();
		$aspectFilePath = $aspectManager->_getAspectFilePath($aspectName);
		if ($aspectFilePath != null) {
			require_once $aspectFilePath;
			return true;
		}
		else {
			return false;
		}
	}
	
	public static function getInstance() {
		return unserialize(file_get_contents(AOWP_AspectManager::_getSerializationLocation()));
	}
	
	public static function getAllAspects() {
		$aspectManager = AOWP_AspectManager::getInstance();
		$allAspectInstanceArray = array();
		foreach ($aspectManager->_aspectFileMap as $aspectName => $aspectDefinitionPath) {
			if (include_once AOWP_ConfigurationManager::getRuntimeAspectFolder() . $aspectDefinitionPath) {
				$aspect = new $aspectName;
				$allAspectInstanceArray = AOWP_AspectManager::_insertAspectWithPriority($aspect, $allAspectInstanceArray);
			}
		}
		// Add default aspects into $allAspectInstanceArray
		$allAspectInstanceArray[] = new AOWP_RequestAroundManageAspect();
//		$allAspectInstanceArray = array(new AOWP_RequestAroundManageAspect());

		return $allAspectInstanceArray;
	}
	private static function _insertAspectWithPriority(AOWP_Aspect $aspect, array $aspectInstanceArray) {
		for ($i = 0; $i < count($aspectInstanceArray); $i++) {
			if ($aspect->getPriority() >= $aspectInstanceArray[$i]->getPriority()) {
				array_splice($aspectInstanceArray, $i, 0, array($aspect));
				return $aspectInstanceArray;
			}
		}
		$aspectInstanceArray[] = $aspect;
		return $aspectInstanceArray;
	}
	
}
?>