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

class Framework
{
	/*
	 *	フレームワークの実行（実体）
	 */
	private static function _run()
	{
		//=======================================
		// フレームワーク初期化処理
		//

		// タイムゾーン
		$default_tz = Profile::getString( s('DEFAULT_TIMEZONE') );
		date_default_timezone_set( $default_tz );
//			ini_set( 'date.timezone', CHARCOAL_TIMEZONE );

		// ロガー初期化
		Logger::init();

		// システムロガー初期化
		if ( Logger::isEnabled() ){

			// システムロガー作成
			$key = s('system');
			$logger = Factory::createLogger( $key );
			Logger::register( $key, $logger );
			log_info( "system",  "ロガーを追加しました[$key]。", __FILE__, __LINE__ );

			// 起動メッセージ
			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__ );

			$profile_name = Profile::getProfileName();
			$profile_config_file = Profile::getConfigFile();
			
			log_info( 'system', "プロファイル名=[$profile_name]" , __FILE__, __LINE__ );
			log_info( 'system', "プロファイル設定ファイル=[$profile_config_file]" , __FILE__, __LINE__ );

		}

		//=======================================
		// 外部ライブラリの使用
		//

		if ( Profile::getBoolean(s('USE_EXTLIB')) ){
			$lib_dirs = Profile::getArray( s('EXTLIB_DIR') );
			foreach( $lib_dirs as $dir ){
				$path = ConfigUtil::processMacro( s($dir) );
				add_include_path( $path );
				log_info( 'system',  "外部ライブラリ参照パスを追加しました[$path]。" );
			}
		}


		//=======================================
		// system以外のロガー作成
		//

		if ( Logger::isEnabled() ){

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

			// ロガーの登録
			foreach( $logger_names as $key ){
				$key = s($key);
				if ( !Logger::isRegistered($key) ){
					$logger = Factory::createLogger( $key );
					Logger::register( $key, $logger );
					log_info( "system",  "ロガーを追加しました[$key]。", __FILE__, __LINE__ );
				}
				else{
					log_info( "system",  "ロガー[$key]はすでに登録済みです。ロガー指定は無視されました。", __FILE__, __LINE__ );
				}
			}

			// プロファイルログ出力
			ProfileSchema::dumpProfileData();
		}

		//=======================================
		// クラスローダの登録
		//
		$class_loaders = Profile::getArray( s('CLASS_LOADERS') );
		foreach( $class_loaders as $loader_name ) 	{
			$loader = Factory::createClassLoader( s($loader_name) );
			ClassLoader::addClassLoader( $loader );
		}

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

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

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

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

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

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

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

		// Requestオブジェクトを作成
		$request = Factory::createRequest( s( CHARCOAL_RUNMODE ) );

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

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

		//=======================================
		// URLマッピング（HTTPのみ）
		//

		if ( CHARCOAL_RUNMODE === 'http'  && Profile::getBoolean(s('USE_URL_MAPPING'))->isTrue() ) {
			log_info( 'system', 'URLマッピングを開始します。', __FILE__, __LINE__ );

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

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

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

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

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

		//=======================================
		// ProcedureKeyが未指定の場合
		//

		// プロファイルから取得
		if ( $proc_key->isEmpty() ){
			$proc_key = Profile::getString( s('DEFAULT_PROCKEY') );
			if ( $proc_key->isEmpty() ){
				log_error( 'system', 'プロファイルにデフォルトプロシージャキー[DEFAULT_PROCKEY]が定義されていません。', __FILE__, __LINE__ );
				_throw( new HttpException('500') );
			}
		}

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

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

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

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

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

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

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

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

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

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

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

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

		DIContainer::destroy();

		// 終了メッセージ
		log_info( 'system', 'charcoalフレームワークを終了します。', __FILE__, __LINE__ );

		// ロガーのシャットダウン
		Logger::terminate();
	}

	/**
	 *	フレームワークを起動
	 */
	public static function run()
	{
		try{
			self::_run();
		}
		catch ( HttpException $e )
		{
			// ステータスコード
			$status = $e->getStatusCode();

			// ユーザ定義のerror_docsを検索
			$html_file = ResourceLocator::getWebAppPath( s('error_docs') , s("$status.html") );

			if ( !is_file($html_file) ){
				// なければデフォルトのerror_docsを検索
				$html_file = ResourceLocator::getSystemPath( s('error_docs') , s("$status.html") );
			}

			if ( is_file($html_file) ){
				// 読み込みと表示
				readfile( $html_file );
				print "<br>";
			}
			else{
				// Errorドキュメントファイルがない
				log_warning( 'system,error', "エラードキュメント($html_file)が存在しません。", __FILE__, __LINE__ );
			}

			// ヘッダ処理
			$header_msg_array = array(
					'401' => 'Unauthorized',
					'403' => 'Forbidden',
					'404' => 'Not Found',
					'500' => 'Internal Server Error',
				);
			$header_msg = $header_msg_array[$status];
			$message = "HTTP/1.0 $status $header_msg";
			header( $message );

			// エラーログ出力
			log_error( 'system,error', $message, __FILE__, __LINE__ );
		}
		catch ( CharcoalException $e )
		{
			include( 'debug/exception_list.php' );
		}
		catch( Exception $e )
		{
			ExceptionStack::dump();
		}
	}
}

return __FILE__;