#-*- 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 xml import xpath
from calculate.lib.cl_template import blocText, xmlDoc
from calculate.lib.format.bind import bind

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

    """
    _comment = "#"
    configName = "apache"
    configVersion = "0.1"
    __headerArea = "[^\<\> \t]+[ \t]+[^\<\> \t]+"
    __openArea = "[ \t]*\<%s\>"%(__headerArea)
    __closeArea = "[ \t]*\<\/[^\<\>]+\>"
    sepFields = "\n"
    reOpen = re.compile(__openArea)
    reClose = re.compile(__closeArea)
    reCloseArea = re.compile(__closeArea + "\s*\Z")
    reComment = re.compile("[ \t]*%s"%(_comment))
    reSepFields = re.compile(sepFields)
    reSeparator = re.compile("[ \t]+")
    reHeader = re.compile(__headerArea)

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

    def postXML(self):
        """Последующая постобработка XML"""
        # Для добавления перевода строки перед закрывающим тегом
        # конфигурационного файла
        xmlFields = xpath.Evaluate("child::fields", self.docObj.body)
        if not (xmlFields and\
                self.docObj.getTypeField(xmlFields[-1]) == "br"):
                    self.docObj.body.appendChild(self.docObj.createField("br",
                                                            [],"",[],
                                                            False,False))
        xmlAreas = xpath.Evaluate("child::area", self.docObj.body)
        for xmlArea in xmlAreas:
            xmlFields = xpath.Evaluate("child::field", xmlArea)
            if not (xmlFields and\
                self.docObj.getTypeField(xmlFields[-1]) == "br"):
                    xmlArea.appendChild(self.docObj.createField("br",
                                                            [],"",[],
                                                            False,False))

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

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

        начальный текстовый блок,
        открывающий блок,
        блок-тело,
        закрывающий блок
        """
        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 = ""
            startBloc = text[openBl.start():openBl.end()]
            headBl = reHeader.search(startBloc)
            if headBl:
                firstBloc = headBl.group(0)
            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, reHeader):
        """Делит текст на области включая вложенные

        возвращает список объектов областей (переменная 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, reHeader)
            areaA.header = first.replace(" ","").replace("\t","")
            areaA.start =  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, reHeader)
                    areas.append(areaA)
            else:
                areaA.fields.append(body)
                areas.append(areaA)


    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) == 3:
                    valueList = nameValue[2:]
                    nameValue =["".join(nameValue[:2])," ".join(valueList)]

                if len(nameValue) > 3:
                    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 textToXML(self):
        """Преобразуем тект в XML"""
        areas = []
        self.splitToAllArea(self.text, areas, self.reOpen, self.reClose,
                       self.reCloseArea,self.reComment,self.reSepFields,
                       self.reHeader)
        docObj = xmlDoc()

        # Создание объекта документ c пустым разделителем между полями
        docObj.createDoc(self.configName, self.configVersion)
        if not areas:
            return docObj
        self.createXML(areas, docObj.getNodeBody(), docObj)
        return docObj
 
