<?php

namespace Heanup\Frame;

/**
 * 简单日志记录
 */
class Logger
{

    private static $logPath = '/data/wwwlogs/';

    private static $logLevel = LOG_ERR;

    private static $maps = array(
        LOG_DEBUG => 'debug',
        LOG_INFO => 'info',
        LOG_NOTICE => 'notice',
        LOG_WARNING => 'warning',
        LOG_ERR => 'err',
        LOG_CRIT => 'crit',
        LOG_ALERT => 'alert',
        LOG_EMERG => 'emerg'
    );

    /**
     * 获取单例
     *
     * @return Logger
     */
    public static function getInstance()
    {
        static $instance = null;
        if (is_null($instance)) {
            $instance = new Logger();
        }
        return $instance;
    }

    /**
     * 设置日志记录错误等级
     *
     * @param int $level
     * @return Logger
     */
    public static function setLogLevel($level = LOG_DEBUG)
    {
        self::$logLevel = intval($level);
        return self::getInstance();
    }

    /**
     * 设置日志记录路径
     *
     * @param
     *            $path
     * @return Logger
     */
    public static function setLogPath($path)
    {
        $path = trim($path);
        if (!empty($path) and is_writable($path)) {
            self::$logPath = $path;
        }
        return self::getInstance();
    }

    public static function debug($message = '', $filename = null)
    {
        return self::log($message, $filename, LOG_DEBUG);
    }

    public static function info($message = '', $filename = null)
    {
        return self::log($message, $filename, LOG_INFO);
    }

    public static function notice($message = '', $filename = null)
    {
        return self::log($message, $filename, LOG_NOTICE);
    }

    public static function warning($message = '', $filename = null)
    {
        return self::log($message, $filename, LOG_WARNING);
    }

    public static function error($message = '', $filename = null)
    {
        return self::log($message, $filename, LOG_ERR);
    }

    public static function crit($message = '', $filename = null)
    {
        return self::log($message, $filename, LOG_CRIT);
    }

    public static function alert($message = '', $filename = null)
    {
        return self::log($message, $filename, LOG_ALERT);
    }

    public static function emerg($message = '', $filename = null)
    {
        return self::log($message, $filename, LOG_EMERG);
    }

    public static function log($message = '', $filename = null, $logType = LOG_DEBUG)
    {
        // 达不到错误记录级别的不与记录，主要是线上环境忽略debug信息
        if ($logType > self::getLogLevel()) {
            return false;
        }
        self::file($message, $filename, $logType);
        return true;
    }

    /**
     * 自定义记录日志
     *
     * @param null $email
     * @param string $message
     * @param string $filename
     * @return bool
     */
    public static function setLog($email = NULL, $message = "", $filename = "")
    {
        if (empty($message) || empty($filename))
            return false;
        $filename = self::getLogPath($filename);
        $message = "[" . date('Y-m-d H:i:s') . "]" . "-[IP:" . self::getClientIp() . "]" . "-[http://" . self::getServerIp() . $_SERVER['REQUEST_URI'] . "]" . ($email ? "-[EMAIL:$email]" : "") . "-[操作:$message]" . "\n";
        return error_log($message, 3, $filename);
    }

    /**
     * 自定义记录日志
     *
     * @param string $message
     * @param string $filename
     * @return bool
     */
    public static function logApi($message = "", $filename = "")
    {
        if (empty($message) || empty($filename))
            return false;
        $filename = self::getLogPath($filename);
        $message = "[" . date('Y-m-d H:i:s') . "]" . "-[IP:" . self::getClientIp() . "]" . "-[http://" . self::getServerIp() . $_SERVER['REQUEST_URI'] . "]" . '[post:' . http_build_query($_POST) . ']' . '[get:' . http_build_query($_GET) . ']' . "-[msg:$message]" . "\n";
        return error_log($message, 3, $filename);
    }

    /**
     * 记录大数据的日志
     *
     * @param
     *            $message
     * @param
     *            $filename
     * @return bool
     */
    public static function bigLog($data)
    {
        if (empty($data))
            return false;
        $filename = self::getBigdataLogPath();
        $message = json_encode($data) . "\r\n";
        return error_log($message, 3, $filename);
    }

    /**
     * 记录简单的日志内容
     *
     * @param
     *            $message
     * @param
     *            $filename
     * @return bool
     */
    public static function singleLog($data, $filename)
    {
        if (is_array($data)) {
            $msg = http_build_query($data);
        } else {
            $msg = $data;
        }
        $filename = self::getLogPath($filename);
        $message = "[" . date('Y-m-d H:i:s') . "][" . $_SERVER['REQUEST_URI'] . "]-[IP:" . self::getClientIp() . "][data:" . $msg . "]\r\n";
        return error_log($message, 3, $filename);
    }

    /**
     * 使用文件记录推送日志
     *
     * @param string $message
     * @param string $filename
     * @param int $logType
     * @return bool
     */
    private static function file($message = '', $filename = null, $logType = LOG_INFO)
    {
        if (!$filename) {
            $logType = intval($logType);
            $filename = self::$maps[$logType];
        }
        $filename = self::getLogPath($filename);
        $message = self::formatFields($message);
        return error_log($message, 3, $filename);
    }

    /**
     * 格式日志记录
     *
     * @param string $message
     * @return string
     */
    private static function formatFields($message)
    {
        if ($message instanceof \Exception) {
            $trace = $message->getTrace();
            $trace = $trace[1];
            $trace = ' ;trace => ' . json_encode($trace);
            $message = $message->getCode() . ' => ' . $message->getMessage() . $trace;
        } elseif ($message) {
            $message = (is_string($message) || is_numeric($message)) ? $message : json_encode($message);
        } else {
            $message = ' - ';
        }
        $data = array();
        $data['time'] = date('Y-m-d H:i:s');
        $data['message'] = trim($message);
        $data['client_ip'] = self::getClientIp();
        $string = '[' . implode("]  [", $data) . ']' . "\n";
        return $string;
    }

    /**
     * 获取错误等级
     *
     * @return int
     */
    private static function getLogLevel()
    {
        return self::$logLevel;
    }

    /**
     * 获取日志路径，如果不存在或者不可写则使用tmp路径
     *
     * @param
     *            $filename
     * @return string
     */
    private static function getLogPath($filename)
    {
        static $path = '';
        if (!$path) {
            if ((!file_exists(self::$logPath))) {
                @mkdir(self::$logPath, 0777, true);
            }
            $path = is_writable(self::$logPath) ? self::$logPath : sys_get_temp_dir();
            $path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . date('Ym') . DIRECTORY_SEPARATOR . date('d') . DIRECTORY_SEPARATOR;
            if (!is_writable($path)) {
                if (!file_exists($path)) {
                    mkdir($path, 0777, true);
                }
            }
        }
        $filename = strtolower(strtr($filename, array(
            ' ' => '',
            DIRECTORY_SEPARATOR => ''
        )));
        $filename = $path . $filename . '.log';
        return $filename;
    }

    /**
     * 获取日志路径，如果不存在或者不可写则使用tmp路径
     *
     * @param
     *            $filename
     * @return string
     */
    private static function getBigdataLogPath()
    {
        $path = '/www/privdata/api.makeup.meitu.com/bigdata/' . date('Ymd') . DIRECTORY_SEPARATOR;
        if ((!file_exists($path))) {
            mkdir($path, 0777, true);
        }
        $filename = date("H") . '_' . self::getServerIp();
        $filename = $path . $filename . '.log';
        return $filename;
    }


    /**
     * 获取客户端Ip
     *
     * @return string|int
     */
    private static function getClientIp()
    {
        static $ip;
        if ($ip) {
            return $ip;
        }
        if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
            $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
        } elseif (isset($_SERVER["HTTP_CLIENT_IP"])) {
            $ip = $_SERVER["HTTP_CLIENT_IP"];
        } elseif (isset($_SERVER["HTTP_CLIENTIP"])) {
            $ip = $_SERVER["HTTP_CLIENTIP"];
        } elseif (isset($_SERVER["HTTP_X_REAL_IP"])) {
            $ip = $_SERVER["HTTP_X_REAL_IP"];
        } elseif (isset($_SERVER["REMOTE_ADDR"])) {
            $ip = $_SERVER["REMOTE_ADDR"];
        } else {
            $ip = '127.0.0.1';
        }
        $pos = strpos($ip, '|');
        if ($pos) {
            $ip = substr($ip, 0, $pos);
        }
        $ip = trim($ip);
        return $ip;
    }

    /**
     * 获取服务器IP
     *
     * @return string
     */
    private static function getServerIp()
    {
        static $ip;
        if ($ip) {
            return $ip;
        }
        if (isset($_SERVER['SERVER_ADDR'])) {
            $ip = $_SERVER['SERVER_ADDR'];
        } else {
            $cmd = "/sbin/ifconfig|grep 'inet addr'|awk '{print $2}'|awk -F':' '{print $2}'|awk '$1 !~ /127.0.0.1/{print}'|tail -n 1";
            $handle = popen($cmd, 'r');
            $ip = trim(fread($handle, 1024));
            pclose($handle);
        }
        return $ip;
    }
}
