#!/usr/bin/python
# -*- coding: latin-1 -*-
# INTEL CONFIDENTIAL
# Copyright 2007 Intel Corporation All Rights Reserved.
#
# The source code contained or described herein and all documents related to the
# source code (“Material”) are owned by Intel Corporation or its suppliers or
# licensors. Title to the Material remains with Intel Corporation or its
# suppliers and licensors. The Material may contain trade secrets and
# proprietary and confidential information of Intel Corporation and its
# suppliers and licensors, and is protected by worldwide copyright and trade
# secret laws and treaty provisions. No part of the Material may be used,
# copied, reproduced, modified, published, uploaded, posted, transmitted,
# distributed, or disclosed in any way without Intel’s prior express written
# permission. 
# No license under any patent, copyright, trade secret or other intellectual
# property right is granted to or conferred upon you by disclosure or delivery
# of the Materials, either expressly, by implication, inducement, estoppel or
# otherwise. Any license under such intellectual property rights must be express
# and approved by Intel in writing.
#
# Include any supplier copyright notices as supplier requires Intel to use.
#
# Include supplier trademarks or logos as supplier requires Intel to use, preceded
# by an asterisk. An asterisked footnote can be added as follows:
# *Third Party trademarks are the property of their respective owners.
#
# Unless otherwise agreed by Intel in writing, you may not remove or alter this
# notice or any other notice embedded in Materials by Intel or Intel’s suppliers
# or licensors in any way.

"""This module contains the methods to create and update the deployment log file

"""
__author__ = 'Todd C Davis'
__Product__ = 'Intel_PDK'

import string, sys, os, os.path
from types import *
from xml.dom.minidom import parse, getDOMImplementation
from xml.parsers.expat import ExpatError
from config import DeploymentStore

CRITICAL = 5
ERROR = 4
WARNING = 3
INFO = 2
DEBUG = 1
NOTSET = 0

LOG_LEVELS = {
    CRITICAL : 'CRITICAL',
    ERROR : 'ERROR',
    WARNING : 'WARNING',
    INFO : 'INFO',
    DEBUG : 'DEBUG',
    NOTSET : 'NOTSET',
    'CRITICAL' : CRITICAL,
    'ERROR' : ERROR,
    'WARNING' : WARNING,
    'INFO' : INFO,
    'DEBUG' : DEBUG,
    'NOTSET' : NOTSET,
}

logLevel = NOTSET

LogFilePath = os.path.join(DeploymentStore,'SystemLog.xml')

def renameSystemLogFile(tag):
    if os.path.exists(LogFilePath) and tag:
        newName = LogFilePath.replace('SystemLog.xml','SystemLog.%s.xml'%tag)
        if os.path.exists(newName):
            os.remove(newName)
        os.rename(LogFilePath,newName)

def openSystemLog():
    try:
        logDOM = parse(LogFilePath) # parse an XML file by name
    
    except (ExpatError, IOError), value:
        #print value
        impl = getDOMImplementation()
        
        logDOM = impl.createDocument(None, "SystemLog", None)
        system_element = logDOM.documentElement
        eventSet_element = logDOM.createElement("eventSet")
        system_element.appendChild(eventSet_element)
    return logDOM

def closeSystemLog(logDOM):
    # encoding is not in Python 2.2 but defaults to encoding="UTF-8"
    prettydoc = logDOM.toprettyxml()
    lines = prettydoc.splitlines(1)
    fp = open(LogFilePath,'w')
    fp.write(lines[0])
    if not lines[1].startswith("<?xml-stylesheet"):
        fp.write('<?xml-stylesheet type="text/xsl" href="SystemLog.xslt"?>\n')
    for line in lines[1:]:
        l = line.strip()
        if l:
            fp.write(line)
    fp.close()
    logDOM.unlink()


def setLogLevel( logDOM,level ):
    if logDOM:
        sLog = logDOM
    else:
        sLog = openSystemLog()
    global logLevel
    if level in LOG_LEVELS:
        if type(level) is StringType:
            logLevel = LOG_LEVELS[level]
        else:
            logLevel = level
        addLogRecord(sLog,'logMgr.py', NOTSET,'minimum log serverity level set to %s'%LOG_LEVELS[logLevel])
    if not logDOM:
        closeSystemLog(sLog)

def getLogSeverity(logDOM):
    if logDOM:
        sLog = logDOM
    else:
        sLog = openSystemLog()
    sev = NOTSET
    sevs = [0, 0, 0, 0, 0, 0]
    for e in sLog.getElementsByTagName("event"):
        cursev = e.getAttribute('level')
        sevno = LOG_LEVELS[cursev]
        if sevno > sev:
            sev = sevno
        sevs[sevno] = sevs[sevno] + 1
    if not logDOM:
        closeSystemLog(sLog)
    print LOG_LEVELS[sev]
    return sev

def setGlobalLogLevelFromLog(sLog):
    global logLevel
    level = 'none'
    for e in sLog.getElementsByTagName("event"):
        if not e.getAttribute('source') == 'logMgr.py':
            continue
        nodes = e.childNodes
        for node in nodes:
            if not node.nodeName == 'message':
                continue
            ns = node.childNodes
            for n in ns:
                if not n.nodeType == sLog.TEXT_NODE:
                    continue
                l = n.nodeValue.strip().split()[-1]
                #print "found message element: %s"% l
                if l in LOG_LEVELS:
                    level = l
                    break
            break
    if level in LOG_LEVELS:
        logLevel = LOG_LEVELS[level]

def addLogRecord(logDOM, src, level, msg):
    if not level in LOG_LEVELS:
        return
    if type(level) is StringType:
        curlevel = LOG_LEVELS[level]
    else:
        curlevel = level
    if logDOM:
        sLog = logDOM
    else:
        sLog = openSystemLog()
    global logLevel
    if src == 'logMgr.py':
        if not msg.split()[-1] in LOG_LEVELS:
            return
        logLevel = LOG_LEVELS[msg.split()[-1]]
    elif logLevel == NOTSET:
        setGlobalLogLevelFromLog(sLog)
    if src != 'logMgr.py' and curlevel < logLevel:
        return
    e = sLog.getElementsByTagName("eventSet")
    assert len(e) == 1
    eSet = e[0]
    
    event_element = sLog.createElement("event")
    import time
    now = time.strftime('%Y-%m-%dT%H:%M:%S',time.localtime(time.time()))
    event_element.setAttribute("date",now)
    event_element.setAttribute("source",src)
    event_element.setAttribute("level",LOG_LEVELS[curlevel])
    message_element = sLog.createElement("message")
    from xml.sax import saxutils
    text = sLog.createTextNode(saxutils.escape(msg).encode('unicode_escape','replace'))
    message_element.appendChild(text)
    event_element.appendChild(message_element)
    eSet.appendChild(event_element)
    if not logDOM:
        closeSystemLog(sLog)

eventDate       = 0
eventSource     = 1
eventSeverity   = 2
eventMessage    = 3

def getLogRecords(logDOM, date='', source='', severity='', lastN=0):
    """
    if 'date' - returns events that occurred since 'date' in ISO format: YYYY-MM-DDTHH:MM:SS
    if 'source' - returns only events with a source == 'source'
    if 'severity' - returns only events with a severity level >= 'severity'
    if 'lastN' - returns at most 'lastN' event records'
    """
    if logDOM:
        sLog = logDOM
    else:
        sLog = openSystemLog()
    events = []
    import datetime
    if date:
        parts = date.split('T')
        dparts = parts[0].split('-')
        if len(dparts) < 3:
            return events
        if not dparts[2]:
            dparts[2] = '1'
        if len(parts) == 2:
            tparts = parts[1].split(':')
            if len(tparts) == 1:
                if not tparts[0]:
                    tparts[0] = '0'
                tparts.append('0')
                tparts.append('0')
            elif len(tparts) == 2:
                if not tparts[1]:
                    tparts[1] = '0'
                tparts.append('0')
            elif not tparts[2]:
                tparts[2] = '0'
        else:
            tparts = ['0','0','0']
        #print dparts, tparts
        try:
            thisDateTime = datetime.datetime(int(dparts[0]),int(dparts[1]),int(dparts[2]),int(tparts[0]),int(tparts[1]),int(tparts[2]))
        except ValueError:
            return events
    for e in sLog.getElementsByTagName("event"):
        dateStamp = e.getAttribute('date')
        if date:
            parts = dateStamp.split('T')
            dparts = parts[0].split('-')
            tparts = parts[1].split(':')
            logDateTime = datetime.datetime(int(dparts[0]),int(dparts[1]),int(dparts[2]),int(tparts[0]),int(tparts[1]),int(tparts[2]))
            if logDateTime < thisDateTime:
                continue
        src = e.getAttribute('source')
        if source and not source == src:
            continue
        sev = e.getAttribute('level')
        if severity and severity in LOG_LEVELS:
            if LOG_LEVELS[sev] < LOG_LEVELS[severity]:
                continue
        message = ''
        nodes = e.childNodes
        for node in nodes:
            if not node.nodeName == 'message':
                continue
            ns = node.childNodes
            for n in ns:
                if not n.nodeType == sLog.TEXT_NODE:
                    continue
                message = n.nodeValue.strip()
        events.append([dateStamp, src, sev, message])
    if not logDOM:
        closeSystemLog(sLog)
    if lastN and len(events) > lastN:
        events = events[-lastN:]
    return events

