<?php
class Logger
{
    protected static $instance;
    private static $logger;

    const ERROR    = 0;
    const WARNING  = 1;
    const INFO     = 2;
    const DEBUG    = 3;
    const DEBUG1   = 4;
    const DEBUG2   = 5;
    const DEBUG3   = 6;
    const DEBUG4   = 7;
    const SQL      = 8;
    const FLOG_MAX = 9;

    const LEVELS = [
        'ERROR', 'WARNING', 'INFO', 'DEBUG', 'DEBUG1', 'DEBUG2', 'DEBUG3', 'DEBUG4', 'SQL', 'FLOG_MAX'
    ];

    public function __construct()
    {
    }

    public static function getLogger()
    {
        if (!self::$instance) {
            self::initLogger();
        }

        return self::$instance;
    }

    public static function initLogger()
    {
        global $savvyext;
        $fluent_host = $savvyext->cfgReadChar('phplogger.host');
        $fluent_port = $savvyext->cfgReadLong('phplogger.port');
        $log_enabled = $savvyext->cfgReadLong('phplogger.enabled');

        if ($log_enabled == 1) {
            self::$logger = new Fluent\Logger\FluentLogger($fluent_host, $fluent_port);
        }
        self::$instance = self::$logger;
    }

    public static function __callStatic($name, $arguments){
        if(is_array($arguments) && count($arguments)>0 && in_array(strtoupper($name), Logger::LEVELS)) {
            $data = $arguments[0];
            $tag = NULL;
            if (count($arguments)>1) {
                $tag = $arguments[1];
            }
            if (count($arguments)>2) {
                $name = $arguments[1];
            	  $tag = $arguments[2];
            }
            $level = Logger::levelByName($name);
            return Logger::log($level, $data, $name, $tag);
        }
        error_log("Logger::__callStatic($name, \$arguments) => Invalid method name!");
    }

    public static function levelByName($name) {
        $val = strtoupper($name);
        if(in_array($val, Logger::LEVELS)) {
            return array_search($val, Logger::LEVELS, false);
        } else {
            return Logger::FLOG_MAX;
        }
    }

    public static function nameByLevel($level) {
        $level = (int)$level;
        return Logger::ERROR < $level || $level > Logger::FLOG_MAX ? Logger::LEVELS[Logger::FLOG_MAX] : Logger::LEVELS[$level];
    }

    public static function log($level, $data = [], $name = NULL, $tag = NULL)
    {
        global $savvyext;
        $clevel = $savvyext->cfgReadLong('phplogger.level');
        $ilevel = (int)$level;
        if ($ilevel > $clevel) {
            error_log("Logger::log() invalid log level! '$level' => '$ilevel' > '$clevel'");
            return; 
        }
        $tag = $tag ?? $savvyext->cfgReadChar('phplogger.tag');
        $name = $name ?? $savvyext->cfgReadChar('phplogger.name');
        $data = [
            "log" => $name,
            "level" => Logger::nameByLevel($level),
            "pid" => getmypid(),
            "zz" => is_array($data) || is_object($data) ? json_encode($data) : $data,
        ];
        if (self::getLogger()) {
            self::getLogger()->post($tag, $data);
        }
    }

}

