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

# Copyright 2008-2012 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 re
from calculate.lib.cl_template import objShare, blocText, xmlDoc

class bind(objShare):
    """Класс для обработки конфигурационного файла типа bind

    """
    _comment = "//"
    configName = "bind"
    configVersion = "0.1"
    __openArea = "{"
    __closeArea = "[ \t]*\}[ \t]*;[ \t]*"
    sepFields = ";"
    reOpen = re.compile(__openArea)
    reClose = re.compile(__closeArea)
    reCloseArea = re.compile(__closeArea + "\s*\Z")
    reComment = re.compile("[ \t]+%s|^%s|(?<=;)%s"%(_comment,_comment,_comment))
    reSepFields = re.compile(sepFields)
    reSeparator = re.compile("[ \t]+")

    def __init__(self,text):
        self.text = text
        self.blocTextObj = blocText()
        # Объект документ
        self.docObj = self.textToXML()
        # Создаем поля-массивы
        self.docObj.postParserList()
        # XML документ
        self.doc = self.docObj.doc

    # Делим область на составные части
    def findOpenClose(self, text, reOpen, reClose, reComment):
        """Делит область на составные части

        начальный текстовый блок,
        открывающий блок,
        блок-тело,
        закрывающий блок
        """
        firstBloc = ""
        startBloc = ""
        bodyBloc = ""
        endBloc = ""
        textLines = text.splitlines()
        findOpen = False
        if textLines:
            findOpen = reOpen.search(textLines[0])
        openBl = reOpen.search(text)
        if findOpen and reComment.split(text)[0].strip():
            blocA = text[openBl.end():]
            firstBloc = text[:openBl.start()]
            startBloc = text[openBl.start():openBl.end()]
            closeBl = reClose.search(blocA)
            endBloc = blocA[closeBl.start():closeBl.end()]
            bodyBloc = blocA[:closeBl.start()]
            return (firstBloc, startBloc, bodyBloc, endBloc)
        else:
            return (firstBloc, startBloc, text, endBloc)


    # Делим текст на области включая вложенные (areas массив областей)
    def splitToAllArea(self, text, areas, reOpen, reClose, reCloseArea,
                       reComment, reSepFields):
        """Делит текст на области включая вложенные

        возвращает список объектов областей (переменная areas)
        """
        class area:
            def __init__(self):
                self.header = False
                self.start = False
                self.fields = []
                self.end = False

        blocs = self.blocTextObj.splitTxtToBloc(text,reOpen,reClose,
                                                reComment,reSepFields)
        for i in blocs:
            areaA = area()
            first,start,body,end = self.findOpenClose(i, reOpen, reCloseArea,
                                     reComment)
            areaA.header = first.replace(" ","").replace("\t","")
            areaA.start = first + start
            areaA.end = end

            if areaA.end:
                blocsA = self.blocTextObj.splitTxtToBloc(body,reOpen,reClose,
                                                        reComment,reSepFields)
                if blocsA and blocsA[0] == body:
                    areaA.fields.append(body)
                    areas.append(areaA)
                else:
                    for ar in blocsA:
                        self.splitToAllArea(ar, areaA.fields, reOpen,
                                            reClose,
                                            reCloseArea, reComment,
                                            reSepFields)
                    areas.append(areaA)
            else:
                areaA.fields.append(body)
                areas.append(areaA)
        return areas


    def setDataField(self, txtLines, endtxtLines):
        """Создаем список объектов с переменными"""
        class fieldData:
            def __init__(self):
                self.name = False
                self.value = False
                self.comment = False
                self.br = False
        fields = []
        field = fieldData()
        z = 0
        for k in txtLines:
            textLine = k + endtxtLines[z]
            z += 1
            findComment = self.reComment.search(textLine)
            if not textLine.strip():
                field.br = textLine
                fields.append(field)
                field = fieldData()
            elif findComment:
                field.comment = textLine
                fields.append(field)
                field = fieldData()
            else:
                pars = textLine.strip()
                nameValue = self.reSeparator.split(pars)
                if len (nameValue) == 1:
                    field.name = ""
                    field.value = textLine.replace(self.sepFields,"")
                    field.br = textLine
                    fields.append(field)
                    field = fieldData()

                if len(nameValue) > 2:
                    valueList = nameValue[1:]
                    nameValue =[nameValue[0]," ".join(valueList).replace(\
                                                            self.sepFields,"")]
                if len(nameValue) == 2:
                    name = nameValue[0]
                    value = nameValue[1].replace(self.sepFields,"")
                    field.name = name.replace(" ","").replace("\t","")
                    field.value = value
                    field.br = textLine
                    fields.append(field)
                    field = fieldData()
        return fields

    def createCaptionTerm(self, header, start, end, docObj):
        """Создание пустой области с заголовком

        при создании области проверяется первый символ заголовка
        и добавляется тег action
        "!" - <action>drop</action>
        "-" - <action>replace</action>
        """
        areaAction = False
        if header:
            if header[0] == "!":
                docObj.createCaption(header[1:], [start,
                                     end.replace("\n","")])
                areaAction = "drop"
            elif header[0] == "-":
                docObj.createCaption(header[1:], [start,
                                     end.replace("\n","")])
                areaAction = "replace"
            else:
                docObj.createCaption(header, [start,
                                    end.replace("\n","")])
        else:
            docObj.createCaption(header, [start,
                                end.replace("\n","")])

        areaXML = docObj.createArea()
        if areaAction:
            docObj.setActionArea(areaXML, areaAction)
        return areaXML

    def createXML(self, areas, rootNode, docObj):
        """Создаем из массивов областей XML"""
        for i in areas:
            if str(i.__class__.__name__) == "area":
                if i.header and i.start:
                    areaXML = self.createCaptionTerm(i.header, i.start,
                                                     i.end.replace("\n",""),
                                                     docObj)
                else:
                    areaXML = rootNode
                for f in i.fields:
                    if str(f.__class__.__name__) == "area":
                        if f.header and f.start:
                            areaXMLChild = self.createCaptionTerm(f.header,
                                                                  f.start,
                                                        f.end.replace("\n",""),
                                                                  docObj)

                            self.createXML(f.fields, areaXMLChild, docObj)

                            areaXML.appendChild(areaXMLChild)
                        else:
                            self.createXML(f.fields, areaXML, docObj)
                        if "\n" in f.end:
                            fieldXMLBr = docObj.createField("br",[],
                                                    "",[],
                                                    False, False)
                            areaXML.appendChild(fieldXMLBr)
                    else:
                        if not f:
                            continue
                        fields = self.splitToFields(f)
                        for field in fields:
                            if field.name != False:
                                fieldXML = self.createFieldTerm(field.name,
                                                                field.value,
                                                            field.br, docObj)
                                areaXML.appendChild(fieldXML)
                                if field.br[-1] == "\n":
                                    fieldXMLBr = docObj.createField("br",[],
                                                                    "",[],
                                                                False, False)
                                    areaXML.appendChild(fieldXMLBr)
                            elif field.comment != False:
                                fieldXML = docObj.createField("comment",
                                                              [field.comment],
                                                              "", [],
                                                              False, False)
                                areaXML.appendChild(fieldXML)
                            elif field.br != False:
                                brText = field.br.replace("\n","")
                                if brText:
                                    fieldXML = docObj.createField('br',
                                                                  [brText],
                                                                  "", [],
                                                                  False, False)
                                else:
                                    fieldXML = docObj.createField('br',
                                                                  [],
                                                                  "", [],
                                                                  False, False)
                                areaXML.appendChild(fieldXML)

                if i.header and i.start:
                    rootNode.appendChild(areaXML)
                if "\n" in i.end:
                    fieldXMLBr = docObj.createField("br",[],
                                                    "",[],
                                                    False, False)
                    rootNode.appendChild(fieldXMLBr)

            else:
                fields = self.splitToFields(i)
                for field in fields:
                    if field.name != False:
                        fieldXML = self.createFieldTerm(field.name,
                                                        field.value,
                                                        field.br, docObj)
                        rootNode.appendChild(fieldXML)
                        if field.br[-1] == "\n":
                            fieldXMLBr = docObj.createField("br",[],"", [],
                                                    False, False)
                            rootNode.appendChild(fieldXMLBr)
                    elif field.comment != False:
                        fieldXML = docObj.createField("comment",
                                                      [field.comment],
                                                      "", [],
                                                      False, False)
                        rootNode.appendChild(fieldXML)
                    elif field.br != False:
                        brText = field.br.replace("\n","")
                        if brText:
                            fieldXML = docObj.createField('br', [brText],"",[],
                                                          False, False)
                        else:
                            fieldXML = docObj.createField('br', [], "", [],
                                                          False, False)
                        rootNode.appendChild(fieldXML)
                #rootNode.appendChild(areaXML)

    def textToXML(self):
        """Преобразуем текст в XML"""
        areas = []
        if self.text.strip():
            self.splitToAllArea(self.text, areas, self.reOpen, self.reClose,
                            self.reCloseArea,self.reComment,self.reSepFields)
        docObj = xmlDoc()
        # Создание объекта документ c пустым разделителем между полями
        docObj.createDoc(self.configName, self.configVersion)
        if not areas:
            return docObj
        self.createXML(areas, docObj.getNodeBody(), docObj)
        return docObj


    def join(self, bindObj):
        """Объединяем конфигурации"""
        if isinstance(bindObj, bind):
            self.docObj.joinDoc(bindObj.doc)

 
