#-*- coding: utf-8 -*-

# Copyright 2008-2013 Calculate Ltd. http://www.calculate-linux.org
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import sys
from xml import xpath
import xml.dom.minidom
from calculate.lib.format.xml_xfce import xml_xfce

from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_lib3',sys.modules[__name__])

class xml_xfcepanel(xml_xfce):
    """Класс для объединения xfce-panel файлов"""
    def __init__(self, text):
        xml_xfce.__init__(self, text)
        self.panelNumbers = {}

    def textToXML(self):
        """Создание из текста XML документа
        Храним xml в своем формате
        """
        if not self.text.strip():
            self.text = '''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE config SYSTEM "config.dtd">
<panels>
</panels>'''
        try:
            self.doc = xml.dom.minidom.parseString(self.text)
        except:
            self.setError(_("The template content is not XML"))
            return False
        self.rootNode = self.doc.documentElement
        self.bodyNode = self.rootNode
        return self.doc

    def setNameBodyNode(self, name):
        """Пустой метод"""
        return True

    def _join(self, xmlNewNode, xmlOldNode, flagRootNode=True, levelNumber=0):
        """Объединение корневой ноды шаблона и корневой ноды файла"""
        xmlNode = xmlNewNode
        childNodes = xmlNode.childNodes
        nextOldNode = xmlOldNode
        flagError = False
        if xmlNode.nodeType ==xmlNode.ELEMENT_NODE:
            n = xmlNode
            path = u''
            nName = u''
            flagArray = False
            nValue = u''
            nAction = u''
            attrName = ''
            attrType = ''
            path = n.tagName
            if path == "items":
                flagArray = True
            if not flagArray:
                if n.hasAttribute("name"):
                    nName = n.getAttribute("name")
                    attrName = u"attribute::name='%s'"%nName
                if n.hasAttribute("value"):
                    nValue = n.getAttribute("value")
            if n.hasAttribute("action"):
                nAction = n.getAttribute("action")
                if not nAction in ("join","replace","drop"):
                    textError = _("In the text of the XML template, "
                      "reserved attribute 'action' comes with an "
                      "incorrect value.\n"
                      "Valid values of the 'action' attribute are: "
                      '(action="join", action="replace", action="drop")')
                    self.setError(textError)
                    return False
            if xmlOldNode.parentNode:
                findAttrStr = ""
                if attrName:
                    findAttrStr = "[%s]"%attrName
                findPath = u"child::%s%s"%(path,findAttrStr)
                # Рабочая нода
                if flagRootNode:
                    workNode = xmlOldNode.parentNode
                else:
                    workNode = xmlOldNode
                oldNodes = xpath.Evaluate(findPath, workNode)
                flagDrop = False
                flagJoin = True
                flagReplace = False
                flagAppend = False
                if nAction == "replace":
                    flagJoin = False
                    flagReplace = True
                elif nAction == "drop":
                    flagJoin = False
                    flagDrop = True
                    if flagRootNode:
                        textError = \
                            _('Incorrect action="drop" in the root node')
                        self.setError(textError)
                        return False
                if path == "panel":
                    flagJoin = False
                    if levelNumber in self.panelNumbers.keys():
                        self.panelNumbers[levelNumber] += 1
                    else:
                        self.panelNumbers[levelNumber] = 0
                if oldNodes:
                    if len(oldNodes)>1 and path != "panel":
                        textError = _("Ambiguity in this template: the "
                                      "same nodes are on a same level")
                        self.setError(textError)
                        return False
                    if path == "panel":
                        if len(oldNodes)<=self.panelNumbers[levelNumber]:
                            nextOldNode = oldNodes[-1]
                            # Добавляем ноду
                            if not flagDrop:
                                flagAppend = True
                                flagReplace = False
                                childNodes = False
                        else:
                            nextOldNode=oldNodes[self.panelNumbers[levelNumber]]
                    else:
                        nextOldNode = oldNodes[0]
                    # Замещаем ноду в случае массива
                    if flagArray and not flagDrop:
                        replaceXmlNode = xmlNode.cloneNode(True)
                        if nAction:
                            replaceXmlNode.removeAttribute("action")
                        workNode.replaceChild(replaceXmlNode,
                                                nextOldNode)
                        flagJoin = False
                        flagReplace = False
                        childNodes = False
                    # Объединение нод
                    if flagJoin:
                        if nextOldNode.hasAttribute("value"):
                            oValue = nextOldNode.getAttribute("value")
                            if nValue != oValue:
                                nextOldNode.setAttribute("value",nValue)
                    # Замещение ноды
                    elif flagReplace:
                        replaceXmlNode = xmlNode.cloneNode(True)
                        if not\
                            self._removeDropNodesAndAttrAction(replaceXmlNode):
                                return False
                        workNode.replaceChild(replaceXmlNode,
                                                nextOldNode)
                        childNodes = False
                    # Удаление ноды
                    elif flagDrop:
                        workNode.removeChild(nextOldNode)
                        childNodes = False
                else:
                    flagAppend = True
                    flagDrop = False
                if flagAppend and not flagDrop:
                    # Добавление ноды
                    childNodes = False
                    if not flagDrop:
                        appendXmlNode = xmlNode.cloneNode(True)
                        if not\
                            self._removeDropNodesAndAttrAction(appendXmlNode):
                                return False
                        workNode.appendChild(appendXmlNode)
            if childNodes:
                for node in childNodes:
                    levelNumber +=1
                    if not self._join(node, nextOldNode, False, levelNumber):
                        flagError = True
                        break
                    levelNumber -= 1
        if flagError:
            return False
        return True

    def join(self, xml_xfceObj):
        """Объединяем конфигурации"""
        if isinstance(xml_xfceObj, xml_xfcepanel):
            try:
                self.joinDoc(xml_xfceObj.doc)
            except:
                self.setError(_("Failed to join the template"))
            return False
        return True
 
