#!/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 system configuration file

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

import os, sys, string
from xml.dom.minidom import parse, getDOMImplementation
from xml.parsers.expat import ExpatError
from logMgr import renameSystemLogFile, addLogRecord,CRITICAL,ERROR,WARNING,INFO,DEBUG
from config import DeploymentStore


def args2attributes(usage, src, name, value, args):
    if src == 'SOURCE' and os.environ.has_key('SOURCE'):
        src = os.environ['SOURCE']
    if name == 'NAME' and os.environ.has_key('NAME'):
        name = os.environ['NAME']
    if value == 'VALUE' and os.environ.has_key('VALUE'):
        value = os.environ['VALUE']
    attributes = {}
    n = ""
    v = ""
    for arg in args:
        parts = arg.split('=')
        if len(parts) > 2:
            errmsg = "Invalid command line for %s %s %s, %s" %(src,name,value,usage)
            addLogRecord(0,src, WARNING, errmsg)
            print(usage)
            sys.exit(-1)
        if len(parts) == 2:
            if not parts[0] and not n:
                errmsg = "Invalid command line for %s %s %s, %s" %(src,name,value,usage)
                addLogRecord(0,src, WARNING, errmsg)
                print(usage)
                sys.exit(-1)
            n = parts[0]
            v = parts[1].strip('\"')
        if len(parts) == 1:
            if not parts[0]:
                continue
            if not n:
                n = arg
                continue
            v = arg.strip('\"')
        if v == 'INSTANCE' and os.environ.has_key('INSTANCE'):
            v = os.environ['INSTANCE']
        if n == 'instance' and not v.isdigit():
            errmsg = "Invalid instance for %s %s %s, %s" %(src,name,value,usage)
            addLogRecord(0,src, WARNING, errmsg)
            print("Invalid instance %s"%v)
            sys.exit(-1)
        attributes[n] = v
        n = ""
        v = ""
    return src, name, value, attributes

InfoFilePath = os.path.join(DeploymentStore,'SystemInfo.xml')

def removeSystemInfoFile():
    if os.path.exists(InfoFilePath):
        os.remove(InfoFilePath)

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

def openSysInfo():
    try:
        systemInfo = parse(InfoFilePath) # parse an XML file by name

    except (ExpatError, IOError), value:
        #print value
        impl = getDOMImplementation()

        systemInfo = impl.createDocument(None, "system", None)
    return systemInfo

def closeSysInfo(systemInfo):
    # encoding is not in 2.2 but defaults to encoding="UTF-8"
    prettydoc = systemInfo.toprettyxml()
    lines = prettydoc.splitlines(1)

    fp = open(InfoFilePath,'w')
    fp.write(lines[0])
    if not lines[1].startswith("<?xml-stylesheet"):
        fp.write('<?xml-stylesheet type="text/xsl" href="SystemInfo.xslt"?>\n')
    for line in lines[1:]:
        l = line.strip()
        if l:
            fp.write(line)
    fp.close()
    systemInfo.unlink()


def getText(nodelist):
    rc = ""
    for node in nodelist:
        if node.nodeType == node.TEXT_NODE:
            rc = rc + node.data
    return string.strip(rc)

def getSourceProperties(sysInfoDOM,src):
    """
    getSourceProperties returns a list of property names  dictionaries for all 'properties' nodes
    NOTE: duplicates in list indicate insufficient attributes given for a unique set of property names
    """
    proplist = []
    if not src.has_key('source'):
        return proplist
    if sysInfoDOM:
        sInfo = sysInfoDOM
    else:
        sInfo = openSysInfo()
    for props in sInfo.getElementsByTagName("properties"):
        if not props.hasAttribute('source'):
            continue
        if not props.getAttribute('source') == src['source']:
            continue
        for attr in props.attributes.keys():
            if not src.has_key(attr):
                continue
            if not src[attr] == props.getAttribute(attr):
                break
        else:   # all given attributes matched
            for prop in props.getElementsByTagName("property"):
                try:
                    pname = getText(prop.getElementsByTagName("name")[0].childNodes)
                    proplist.append(pname + "=" + getText(prop.getElementsByTagName("value")[0].childNodes))
                    # duplicates in list indicate insufficient attributes given
                except IndexError:
                    continue
    if not sysInfoDOM:
        sInfo.unlink()
    return proplist

def getPropertySources(sysInfoDOM):
    """
    getPropertySources returns a list of attribute dictionaries for all 'properties' nodes
    """
    if sysInfoDOM:
        sInfo = sysInfoDOM
    else:
        sInfo = openSysInfo()
    srclist = []
    for props in sInfo.getElementsByTagName("properties"):
        if not props.hasAttribute('source'):
            continue
        srcattrs = {}
        for attr in props.attributes.keys():
            srcattrs[attr] = props.getAttribute(attr)
        srclist.append(srcattrs)
    if not sysInfoDOM:
        sInfo.unlink()
    return srclist

def locateProperties(sInfo, src, attributes={}, matchAll=0):
    rprops = []
    if not attributes.has_key('source'):
        attributes['source'] = src
    for props in sInfo.getElementsByTagName("properties"):
        if matchAll and not len(attributes) == len(props.attributes.keys()):
            #print "len %d does not match %d" % (len(props.attributes.keys()), len(attributes))
            continue
        for attr in attributes:
            if attr in props.attributes.keys():
                if props.getAttribute(attr) == attributes[attr]:
                    continue
                else:
                    #if matchAll:
                    #    print "attr value %s does not match %s" % (props.getAttribute(attr), attributes[attr])
                    break
            else:
                #if matchAll:
                    #print "Attribute %s not found" % attr
                 break
        else:   # (no break) all attributes match
            rprops.append(props)
    return rprops

def locateProperty(sInfo, src, name, attributes={}, matchAll=0):
    rprop = []
    for props in locateProperties(sInfo, src, attributes, matchAll):
        for prop in props.getElementsByTagName("property"):
            try:
                if not string.strip(name) == getText(prop.getElementsByTagName("name")[0].childNodes):
                    continue
                rprop.append(prop)
            except IndexError:
                continue
    return rprop

def queryProperty(sysInfoDOM, src, name, value, attributes={}):
    ret = -1
    thisValue = ''
    if sysInfoDOM:
        sInfo = sysInfoDOM
    else:
        sInfo = openSysInfo()
    rprop = locateProperty(sInfo, src, name, attributes)
    for prop in rprop:
        try:
            thisValue = getText(prop.getElementsByTagName("value")[0].childNodes)
            if value == '-':
                print thisValue
                ret = 0
            else:
                if value == thisValue:
                    ret = 1
                else:
                    ret = 0
        except IndexError:
            continue
    if not sysInfoDOM:
        sInfo.unlink()
    return ret, thisValue

def countProperty(sysInfoDOM, src, name, attributes={}):
    if sysInfoDOM:
        sInfo = sysInfoDOM
    else:
        sInfo = openSysInfo()
    rprop = locateProperty(sInfo, src, name, attributes)
    if not sysInfoDOM:
        sInfo.unlink()
    return len(rprop)

def addProperty(sysInfoDOM, src, name, value, attributes={}):
    if sysInfoDOM:
        sInfo = sysInfoDOM
    else:
        sInfo = openSysInfo()
    rprops = locateProperties(sInfo, src, attributes, 1)
    for props in rprops:
        assert len(rprops) == 1
        for prop in props.getElementsByTagName("property"):
            try:
                if not string.strip(name) == getText(prop.getElementsByTagName("name")[0].childNodes):
                    continue
                if string.strip(value) == getText(prop.getElementsByTagName("value")[0].childNodes):
                    break
                value_element = prop.getElementsByTagName("value")[0]
                text = sInfo.createTextNode(string.strip(value))
                value_element.replaceChild(text,value_element.firstChild)
                break
            except IndexError:
                if not prop.getElementsByTagName("name"):
                    continue
                if not prop.getElementsByTagName("value"):
                    value_element = sInfo.createElement("value")
                    prop.appendChild(value_element)
                    text = sInfo.createTextNode(string.strip(value))
                    value_element.appendChild(text)
                    break
        else: # (no break) add new property
            property_element = sInfo.createElement("property")
            props.appendChild(property_element)
            name_element = sInfo.createElement("name")
            property_element.appendChild(name_element)
            text = sInfo.createTextNode(string.strip(name))
            name_element.appendChild(text)
            value_element = sInfo.createElement("value")
            property_element.appendChild(value_element)
            text = sInfo.createTextNode(string.strip(value))
            value_element.appendChild(text)
            break
        break
    else: # (no break) no matching properties element
        properties_element = sInfo.createElement("properties")
        properties_element.setAttribute("source",src)
        for attr in attributes:
            properties_element.setAttribute(attr,attributes[attr])
        sInfo.documentElement.appendChild(properties_element)
        property_element = sInfo.createElement("property")
        properties_element.appendChild(property_element)
        name_element = sInfo.createElement("name")
        property_element.appendChild(name_element)
        text = sInfo.createTextNode(string.strip(name))
        name_element.appendChild(text)
        value_element = sInfo.createElement("value")
        property_element.appendChild(value_element)
        text = sInfo.createTextNode(string.strip(value))
        value_element.appendChild(text)
    if not sysInfoDOM:
        closeSysInfo(sInfo)
