<?php
/**
*  フレームワークのメインクラス
*
* PHP version 5
*
* @package    core
* @author     stk2k <stk2k@sazysoft.com>
* @copyright  2008 stk2k, sazysoft
*/

class charcoal_Framework
{
	/*
	 *	フレームワークを起動
	 */
	public static function run()
	{
		try{
			//=======================================
			// ログの初期化
			//

			// プロファイルに設定されているロガーを取得
			$logger_names = charcoal_Profile::getArray( 'LOG_LOGGERS' );

			// ロガーの登録
			foreach( $logger_names as $key ){
				$logger = charcoal_LoggerFactory::create( $key );
				charcoal_Logger::append( $key, $logger );
			}

			// ロガー出力を開始
			charcoal_Logger::init();

			// 起動メッセージ
			log_info( 'system,config', '===========================================================', __FILE__, __LINE__ );
			log_info( 'system,config', ' CHARCOAL framework version 1.0 (c)sazysoft,stk2k          ', __FILE__, __LINE__ );
			log_info( 'system,config', '===========================================================', __FILE__, __LINE__ );

			log_info( 'system', 'charcoalフレームワークを開始します。', __FILE__, __LINE__ );


			//=======================================
			// クラスローダの登録
			//
			$class_loaders = charcoal_Profile::getArray('CLASS_LOADERS');
			if ( $class_loaders && is_array($class_loaders) ) {
				foreach( $class_loaders as $loader_name ) 	{
					$loader = charcoal_ClassLoaderFactory::create( $loader_name );
					charcoal_ClassLoader::addClassLoader( $loader );
				}
			}

			//=======================================
			// セッションハンドラの作成
			//

			if ( charcoal_Profile::getBoolean('USE_SESSION') ) {
				log_info( 'system', 'セッションハンドラの作成を開始します。', __FILE__, __LINE__ );

				// セッションハンドラ名の取得
				$session_handler_name = charcoal_Profile::getString( 'SESSION_HANDLER_NAME' );

				// セッションハンドラの作成
				$session_handler = charcoal_SessionHandlerFactory::create( $session_handler_name );

				log_info( 'system', 'セッションハンドラの作成を終了しました。', __FILE__, __LINE__ );
			}

			//=======================================
			// Requestパラメータの取得
			//

			log_info( 'system', 'Requestパラメータの解析を開始します。', __FILE__, __LINE__ );

			// Requestオブジェクトを作成
			$request = new charcoal_Request();

			$proc_key = $request->get( PROC_KEYWORD );

			log_info( 'system', "プロシージャキーは[$proc_key]です。", __FILE__, __LINE__ );

			//=======================================
			// URLマッピング
			//

			if ( charcoal_Profile::getBoolean('USE_URL_MAPPING') ) {
				log_info( 'system', 'URLマッピングを開始します。', __FILE__, __LINE__ );

				// URLマッパー名
				$url_mapper_name = charcoal_Profile::getString('URL_MAPPER' );

				// URLマッパーを作成
				$url_mapper = charcoal_URLMapperFactory::create( $url_mapper_name );

				// マッピング実行
				$url_mapper->mapURL( $request );

				$proc_key = $request->getString( PROC_KEYWORD );

				log_info( 'system', "プロシージャキーは[$proc_key]です。", __FILE__, __LINE__ );
			}

			//=======================================
			// リクエストディスパッチ
			//

			log_info( 'system', 'Dispatchを開始します。', __FILE__, __LINE__ );

			// ディスパッチャ名を設定ファイルから取得
			$dispacher_name = charcoal_Profile::getString( 'DISPATCHER' );

			// ディスパッチャを作成
			$dispatcher = charcoal_DispatcherFactory::create( $dispacher_name );

			// ディスパッチ
			$proc_key = $dispatcher->dispatch( $request );

			log_info( 'system', "Dispatchを終了します。ディスパッチ先=[$proc_key]", __FILE__, __LINE__ );

			//=======================================
			// Procedureの作成
			//

			log_info( 'system', "プロシージャ[$proc_key]を作成します。", __FILE__, __LINE__ );

			// プロシージャを作成
			list( $procedure, $proc_name ) = charcoal_ProcedureFactory::create( $proc_key );

			log_info( 'system', "プロシージャ[$proc_name]を作成しました。", __FILE__, __LINE__ );

			//=======================================
			// コンテナの作成と起動
			//

			log_info( 'system', 'DIコンテナの作成を開始します。', __FILE__, __LINE__ );

			// DIコンテナを作成
			charcoal_DIContainer::createContainer( $procedure );

			//=======================================
			// Responseの作成
			//

			log_info( 'system', 'Responseオブジェクトを作成します。', __FILE__, __LINE__ );

			// Requestオブジェクトを作成
			$response = new charcoal_Response();

			//=======================================
			// ProcedureContextの作成
			//

			log_info( 'system', 'ProcedureContextオブジェクトを作成します。', __FILE__, __LINE__ );

			// セッションを作成
			$session = new charcoal_Session();

			// ProcedureContextオブジェクトを作成
			$context = new charcoal_ProcedureContext( $proc_name, $procedure, $session );

			//=======================================
			// セッションの開始
			//
			if ( charcoal_Profile::getBoolean('USE_SESSION') ) {
				$session->start();
				$session->restore();
			}

			//=======================================
			// Procedureの実行
			//

			log_info( 'system', 'プロシージャ[$proc_name]を実行します。', __FILE__, __LINE__ );

			// プロシージャの実行
			$procedure->execute( $request, $context, $response );

			log_info( 'system', 'プロシージャ[$proc_name]を実行しました。', __FILE__, __LINE__ );

			//=======================================
			// 終了処理
			//

			// セッション情報の保存
			if ( charcoal_Profile::getBoolean('USE_SESSION') ) {
				$session->save();
				$session->close();
			}

			//=======================================
			// コンテナの破棄
			//

			log_info( 'system', 'DIコンテナを破棄します。', __FILE__, __LINE__ );

			charcoal_DIContainer::destroy();

			// 終了メッセージ
			log_info( 'system', 'charcoalフレームワークを終了します。', __FILE__, __LINE__ );
		}
		catch ( charcoal_HttpException $e )
		{
			// プロファイルからステータスコードに対応するドキュメントを取得
			$error_doc = charcoal_Profile::getString( 'ERROR_DOC_' . $e->getStatusCode() );

			// ユーザ定義のerror_docsを検索
			$html_file = charcoal_ResourceLocator::getPath( charcoal_ResourcePath::WEBAPP, '/error_docs/' . $error_doc );

			if ( !is_file($html_file) ){
				// なければデフォルトのerror_docsを検索
				$html_file = CHARCOAL_HOME . '/error_docs/' . $error_doc;
			}

			if ( is_file($html_file) ){
				// 読み込みと表示
				readfile( $html_file );
				print "<br>";
			}

			// ヘッダ処理
			switch ( $e->getStatusCode() ){
			case 401:
				header('HTTP/1.0 401 Unauthorized');
				break;
			case 403:
				header('HTTP/1.0 403 Forbidden');
				break;
			case 404:
				header("HTTP/1.0 404 Not Found");
				break;
			case 500:
				header('HTTP/1.0 500 Internal Server Error');
				break;
			}
		}
		catch ( charcoal_Exception $e ){

			$cause_list = $e->getCauseList();

			$cause_list[] = new charcoal_Exception( 'Framework#run() failed', $e );

			include( 'classes/core/exception_list.php' );

		}
	}
}
