<?

class LogLevel {

    static $NONE = null;
    static $INFO = null;
    static $WARN = null;
    static $ERROR = null;
    static $SEVERE = null;
    static $DEBUG = null;
    static $TRACK = null;
    static $ALL = null;

    private $value = null;

    public static $map;

    public function __construct($value) {
        $this->value = $value;
    }

    public static function init () {
        self::$NONE = new LogLevel(0);
        self::$INFO = new LogLevel(1);
        self::$WARN = new LogLevel(2);
        self::$ERROR = new LogLevel(3);
        self::$SEVERE = new LogLevel(4);
        self::$DEBUG = new LogLevel(5);
        self::$TRACK = new LogLevel(6);
        self::$ALL = new LogLevel(7);
        //static map to get object by name - example Enum::get("INIT") - returns Enum::$INIT object;
        self::$map = array (
            self::$NONE->getValue() 	=> [ "NONE" 	, $GLOBALS['_LOGFILE_INFO']		]
            , self::$INFO->getValue() 	=> [ "INFO" 	, $GLOBALS['_LOGFILE_INFO']		]
            , self::$WARN->getValue() 	=> [ "WARN" 	, $GLOBALS['_LOGFILE_INFO']		]
            , self::$ERROR->getValue() 	=> [ "ERROR" 	, $GLOBALS['_LOGFILE_ERROR']	]
            , self::$SEVERE->getValue() => [ "SEVERE" 	, $GLOBALS['_LOGFILE_ERROR']	]
            , self::$DEBUG->getValue() 	=> [ "DEBUG" 	, $GLOBALS['_LOGFILE_DEBUG']	]
            , self::$TRACK->getValue() 	=> [ "TRACK" 	, $GLOBALS['_LOGFILE_TRACK']	]
            , self::$ALL->getValue() 	=> [ "ALL" 		, $GLOBALS['_LOGFILE_INFO'] 	]
        );
    }

    public static function get($element) {
        if($element == null)
            return null;
        return self::$map[$element];
    }

    public function getValue() {
        return $this->value;
    }

    public function equals(LogLevel $element) {
        return $element->getValue() == $this->getValue();
    }

    public function __toString () {
        return self::$map[$this->getValue()][0];
    }
}
LogLevel::init();

class Logger {

  private $LOGLEVEL = null;//LogLevel::$SEVERE;
  private $MSG_TYPE = 3;
  private $logger_name = null;

  const DELIMITER = "|";

  static $logger;

  function __construct($n = '') {
    $level = $GLOBALS['_LOGLEVEL'];
    if (isset($level) && !empty($level)) {
      $this->LOGLEVEL = $level;
    }
    $this->logger_name = $n;
  }

  public static function getInstance($n = 'GLOBAL') {

    if (!isset($logger[$n])) {
      $logger[$n] = new Logger($n);
    }

    return $logger[$n];
  }

  private function prefix($str, $level) {
    $prefix = date('Y-m-d H:i:s|').$level->__toString().'|'.$this->logger_name;

    return $prefix.": ".$str."\n";
  }

  /**
   * Function log()
   * Arguments:
   * 	1 - LogLevel
   *	2 - String
   *    3.. - use vsprintf($2, $3..)
   */
  public function log() {
	// prepare arguments
    $argv = func_get_args();
    $level = $argv[0];
    $other = $argv[1];
	if (is_array($other)) {
		if (sizeof($other) > 1) {
    		$tmp = $other[0];
    		unset($other[0]);
   			$str = vsprintf($tmp, $other);
		} else
			$str = $other[0];
	} else
		$str = $other;

    if ($this->LOGLEVEL != null && $this->LOGLEVEL->getValue() >= $level->getValue()) {
      switch ($this->MSG_TYPE) {
        case 0:
          error_log($str, $this->MSG_TYPE);
          break;
        case 3:
          error_log($this->prefix($str, $level), $this->MSG_TYPE, LogLevel::$map[$level->getValue()][1]);
          break;
        default:
          // for furture use, send mail or SAPI logging
          error_log($str, $this->MSG_TYPE);
      }
    }
  }

  /**
	info(), warn(), error(), severe(), debug() Function
	arguments:
		1 - prefix e.g. SESSION-ID
		2 - string
		3... - use sprintf($2, $3, $4, $5, ...)
   */
  function info() {
    $this->log(LogLevel::$INFO, func_get_args());
  }

  function warn($str) {
    $this->log(LogLevel::$WARN, func_get_args());
  }

  function error($str) {
    $this->log(LogLevel::$ERROR, func_get_args());
  }

  function severe($str) {
    $this->log(LogLevel::$SEVERE, func_get_args());
  }

  function debug($str) {
    $this->log(LogLevel::$DEBUG, func_get_args());
  }

  function tracking($str) {
	$this->log(LogLevel::$TRACK, func_get_args());
  }

}
