#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys,os
import datetime
import threading
import pypibot.assistant as assistant
import platform
if assistant.is_python3():
    import _thread
else:
    import thread
import traceback
"""
%a Locale’s abbreviated weekday name.   
%A Locale’s full weekday name.   
%b Locale’s abbreviated month name.   
%B Locale’s full month name.   
%c Locale’s appropriate date and time representation.   
%d Day of the month as a decimal number [01,31].   
%H Hour (24-hour clock) as a decimal number [00,23].   
%I Hour (12-hour clock) as a decimal number [01,12].   
%j Day of the year as a decimal number [001,366].   
%m Month as a decimal number [01,12].   
%M Minute as a decimal number [00,59].   
%p Locale’s equivalent of either AM or PM. (1) 
%S Second as a decimal number [00,61]. (2) 
%U Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0. (3) 
%w Weekday as a decimal number [0(Sunday),6].   
%W Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0. (3) 
%x Locale’s appropriate date representation.   
%X Locale’s appropriate time representation.   
%y Year without century as a decimal number [00,99].   
%Y Year with century as a decimal number.   
%Z Time zone name (no characters if no time zone exists).   
%% A literal '%' character. 

"""
isWindows=False
if platform.system()=='Windows':
    isWindows=True
defaultEncodeing="utf8"
if "-utf8" in sys.argv:
    defaultEncodeing="utf-8"
if "-gbk" in sys.argv:
    defaultEncodeing="gbk"

TRACE=5
DEBUG=4
INFORMATION=3
WARNING=2
ERROR=1
NONE=0

MAX_MSG_SIZE = 4096

def getLevelFromString(level):
    level=level.lower()
    if level=='t' or level=='trace':return 5
    elif level=='d' or level=='debug':return 4
    elif level=='i' or level=='info':return 3
    elif level=='w' or level=='wran':return 2
    elif level=='e' or level=='error':return 1
    else :return 0
def getLevelString(level):
    if level==TRACE:return "T"
    elif level==DEBUG:return "D"
    elif level==INFORMATION:return "I"
    elif level==WARNING:return "W"
    elif level==ERROR:return "E"
    else:return "N"
class PibotLog:
    def __init__(self):
        self.isEnableControlLog=True
        self.fileTemple=None
        self.filePath=""
        self.level=5
        self._lock=threading.RLock()
        self.fd=None
        self.fd_day=-1
    def setLevel(self,level):
        self.level=getLevelFromString(level)
    def enableControllog(self,enable):
        self.isEnableControlLog=enable
    def enableFileLog(self,fileName):
        self.fileTemple=fileName
        self.updateFilelog()
    def updateFilelog(self):
        fn=assistant.SF(self.fileTemple)
        if fn!=self.filePath:
            self.i("new log file:%s",fn)
            if self.fd:
                self.fd.close()
                self.fd=None
                self.fd_day=-1
                self.filePath=""
            try:
                path=os.path.dirname(fn)
                if path!="" and not os.path.isdir(path):os.makedirs(path)
                self.fd=open(fn,mode="w")
                try:
                    linkfn = fn.split(".log.", 1)[0] + ".INFO"
                    if os.path.exists(linkfn):
                        os.remove(linkfn)
                    (filepath, tempfilename) = os.path.split(fn)
                    os.symlink(tempfilename, linkfn)
                except:
                    pass
                self.fd_day=datetime.datetime.now().day
                self.filePath=fn
            except Exception as e:
                print("open file fail!file=%s,err=%s"%(fn,e))
    def _output(self,level,msg,args):
        if self.level<level:return
        try:
            if len(args)>0:
                t=[]
                for arg in args:
                    if isinstance(arg,Exception):
                        t.append(traceback.format_exc(arg).decode('utf-8'))
                    elif isinstance(arg,bytes) :
                        t.append(arg.decode('utf-8'))
                    else:
                        t.append(arg) 
                args=tuple(t)
                try:
                    msg=msg%args
                except:
                    try:
                        for arg in args:
                            msg=msg+str(arg)+" "
                    except Exception as e:
                        msg=msg+"==LOG ERROR==>%s"%(e)
            if len(msg)>MAX_MSG_SIZE:msg=msg[0:MAX_MSG_SIZE]
            now=datetime.datetime.now()
            msg=msg+"\r\n"
            if assistant.is_python3():
                id = _thread.get_ident()
            else:
                id = thread.get_ident()
            s="[%s] %04d-%02d-%02d %02d:%02d:%02d.%03d (0x%04X):%s"%(getLevelString(level),now.year,now.month,now.day,now.hour,now.minute,now.second,now.microsecond/1000,(id>>8)&0xffff,msg)
            prefix=''
            suffix=''
            if not isWindows:
                suffix='\033[0m'
                if level==TRACE:
                    prefix='\033[0;37m'
                elif level==DEBUG:
                    prefix='\033[1m'
                elif level==INFORMATION:
                    prefix='\033[0;32m'          
                elif level==WARNING:
                    prefix='\033[0;33m'          
                elif level==ERROR:
                    prefix='\033[0;31m'          
                else:
                    pass
            self._lock.acquire()
            try:
                if self.isEnableControlLog:
                    sys.stdout.write((prefix+s+suffix))
                if self.fd:
                    if self.fd_day!=now.day:
                        self.updateFilelog()
                    if assistant.is_python3():
                        self.fd.write(s)
                    else:
                        self.fd.write(s.encode('utf-8'))
                    self.fd.flush()
            finally:
                self._lock.release()
        except Exception as e:
            if assistant.is_python3():
                print(e)
            else:
                print("PibotLog._output crash!err=%s"%traceback.format_exc(e))

    def trace(self,msg,*args):
        self._output(TRACE,msg,args)
    def t(self,msg,*args):
        self._output(TRACE,msg,args)
    def debug(self,msg,*args):
        self._output(DEBUG, msg,args)
    def d(self,msg,*args):
        self._output(DEBUG, msg,args)
    def info(self,msg,*args):
        self._output(INFORMATION, msg,args)
    def i(self,msg,*args):
        self._output(INFORMATION, msg,args)
    def warn(self,msg,*args):
        self._output(WARNING, msg,args)
    def w(self,msg,*args):
        self._output(WARNING, msg,args)
    def error(self,msg,*args):
        self._output(ERROR, msg,args)
    def e(self,msg,*args):
        self._output(ERROR, msg,args)
    def _log(self,level,msg,args):
        self._output(level, msg,args)
    def createNamedLog(self,name):
        return NamedLog(name)
log=PibotLog()
class NamedLog:
    def __init__(self,name=None):
        global log
        self.name=''
        if name:
            self.name='['+name+']'
        self.log=log
    def trace(self,msg,*args):
        msg=self.name+msg
        self.log._log(TRACE,msg,args)
    def t(self,msg,*args):
        msg=self.name+msg
        self.log._log(TRACE,msg,args)
    def debug(self,msg,*args):
        msg=self.name+msg
        self.log._log(DEBUG, msg,args)
    def d(self,msg,*args):
        msg=self.name+msg
        self.log._log(DEBUG, msg,args)
    def info(self,msg,*args):
        msg=self.name+msg
        self.log._log(INFORMATION, msg,args)
    def i(self,msg,*args):
        msg=self.name+msg
        self.log._log(INFORMATION, msg,args)
    def warn(self,msg,*args):
        msg=self.name+msg
        self.log._log(WARNING, msg,args)
    def w(self,msg,*args):
        msg=self.name+msg
        self.log._log(WARNING, msg,args)
    def error(self,msg,*args):
        msg=self.name+msg
        self.log._log(ERROR, msg,args)
    def e(self,msg,*args):
        msg=self.name+msg
        self.log._log(ERROR, msg,args)
    
if __name__ == "__main__":
    log.trace("1%s","hello")
    log.debug("2%d",12)
    try:
        raise Exception("EXC")
    except Exception as e:
        log.info("3%s",e)
    log.warn("1")
    log.error("1")
    #log.enableFileLog("$(scriptpath)test_$(Date8)_$(filenumber2).log")
    log.trace("1")
    log.debug("1")
    log.info("1")
    log.warn("1")
    log.error("1")
    log=NamedLog("test")
    log.d("1")
    log.i("1")
    log.warn("1")
    log.error("1=%d,%s",100,e)
