<?php
/**
* ロガーのフロントエンドインタフェース
*
* PHP version 5
*
* @package    core
* @author     stk2k <stk2k@sazysoft.com>
* @copyright  2008 stk2k, sazysoft
*/

class Logger 
{
	static $loggers = array();
	static $enabled = FALSE;

	const LOGLEVEL_FATAL     = 100;		// FATAL
	const LOGLEVEL_ERROR     = 200;		// ERROR
	const LOGLEVEL_WARNING   = 300;		// WARNING
	const LOGLEVEL_INFO      = 400;		// INFO
	const LOGLEVEL_DEBUG     = 500;		// DEBUG
	const LOGLEVEL_TRACE     = 600;		// TRACE

	/**
	 * 初期化
	 */
	public static function init()
	{
		self::$enabled = Profile::getBoolean( 'LOG_ENABLED' ) ? TRUE : FALSE;
	}

	/**
	 * 終了
	 */
	public static function terminate()
	{
		self::$enabled = FALSE;
	}

	/*
	 *	ロガーを追加
	 */
	public static function append( $key, ILogger $logger )
	{
		// ロガーを配列にセット
		self::$loggers[ "$key" ] = $logger;
	}

	/*
	 *	１行出力
	 */
	public static function writeln( $target, $message, $file, $line )
	{
		if ( !self::$enabled ){
			return;
		}
		
		// ログレベルとロガー名を取得
		list( $level, $logger_names ) = self::_getLevelAndTargetList( $target );

		self::_writelnAll( $level, $logger_names, $message, $file, $line );
	}
	
	/*
	 *	配列出力
	 */
	public static function writeArray( $target, $ary, $file, $line )
	{
		if ( !self::$enabled ){
			return;
		}

		// ログレベルとロガー名を取得
		list( $level, $logger_names ) = self::_getLevelAndTargetList( $target );

		foreach( $ary as $key => $value ){
			$message = "[$key]=>$value";
			self::_writelnAll( $level, $logger_names, $message, $file, $line );
		}
	}

	/*
	 *	登録されているロガーすべてにログ出力
	 */
	private static function _writelnAll( $level, $logger_names, $message, $file, $line )
	{
		// ログレベル設定を取得
		$profile_level = Profile::getString( 'LOG_LEVEL' );

		if ( !$profile_level ){
			// LOG_LEVELが設定されていない場合は、WARNING以上出力
			$profile_level = self::LOGLEVEL_WARNING;
		}

		// プロファイルに設定したレベル以下ならば出力しない
		$cmp = self::_compareLogLevel($level,$profile_level);
		if ( $cmp > 0 ){
			return;
		}

		// 対象ロガーに対してのみ出力
		foreach( $logger_names as $key ){
			if ( isset( self::$loggers[ $key ] ) ){
				$logger = self::$loggers[ $key ];
				$logger->writeln( $key, $level, $message, $file, $line );
			}
		}
	}

	/*
	 *	ログレベル値の取得
	 *
	 */
	private static function _getLogLevelValue( $level )
	{
		switch( $level ){
		case 'F':	$ret = self::LOGLEVEL_FATAL;		break;		// FATAL
		case 'E':	$ret = self::LOGLEVEL_ERROR;		break;		// ERROR
		case 'W':	$ret = self::LOGLEVEL_WARNING;		break;		// WARNING
		case 'I':	$ret = self::LOGLEVEL_INFO;			break;		// INFO
		case 'D':	$ret = self::LOGLEVEL_DEBUG;		break;		// DEBUG
		case 'T':	$ret = self::LOGLEVEL_TRACE;		break;		// TRACE
		default:	$ret = self::LOGLEVEL_INFO;			break;		// as INFO
		}
		return $ret;
	}

	/*
	 *	ログレベルの比較
	 *
	 */
	private static function _compareLogLevel( $lv1, $lv2 )
	{
		$lv1 = self::_getLogLevelValue($lv1);
		$lv2 = self::_getLogLevelValue($lv2);

		return ($lv1 - $lv2);
	}

	/*
	 *	targetからログレベルとロガー名を取得
	 *
	 *	target文字列のフォーマット：
	 *
	 *  [ログレベル]:[ロガー名],[ロガー名],...
	 *	ex) "I:app,debug,sql"
	 */
	private static function _getLevelAndTargetList( $target )
	{
		// コロンで分割
		list($level,$logger_names) = explode( ":" , "$target" );

		// ロガー名リスト
		$logger_names = explode( "," , $logger_names );

		return array( $level, $logger_names );
	}

}
