# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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
import os
import tempfile
import shutil
from .utilities import bash
class configFileOps:
    class entry:
        def __init__(self, name, value, op, separator):
            self.name = name
            self.value = value
            self.state = "new"
            self.op = op
            self.separator = separator
        def setState(self, state):
            self.state = state
        def getState(self):
            return self.state

    def __init__(self, fileName, cfg=None):
        self.fileName = fileName
        self.entries = []
        self.backups = []

        if cfg is not None:
            cfg.cfoHandlers.append(self)

    def addEntry(self, name, value, separator="="):
        e = self.entry(name, value, "add", separator)
        self.entries.append(e)

    def rmEntry(self, name, value, separator="="):
        entry = self.entry(name, value, "rm", separator)
        self.entries.append(entry)

    def getEntry(self, name, separator="="):
        try:
            ctx = open(self.fileName).read(-1)
            match = re.search("^" + name + ".*", ctx, re.MULTILINE)
            if match is None:
                return ""
            line = match.group(0).split(separator, 1)
            return line[1]
        except:
            return ""

    def save(self):
        newLines = []
        if os.path.exists(self.fileName) and os.path.isfile(self.fileName):
            fp = open(self.fileName, "r")
            for line in fp.readlines():
                matched = False
                for entry in self.entries:
                    if entry.op == "add":
                        if entry.separator == "=":
                            matchString = "^\ *" + entry.name + ".*"
                        elif entry.separator == " ":
                            matchString = "^\ *" + entry.name + "\ *" + entry.value
                    else:
                        if entry.separator == "=":
                            matchString = "^\ *" + entry.name + "\ *=\ *" + entry.value
                        else:
                            matchString = "^\ *" + entry.name + "\ *" + entry.value

                    match = re.match(matchString, line)
                    if match is not None:
                        if entry.op == "add" and entry.separator == "=":
                            newline = "\n" + entry.name + "=" + entry.value + "\n"
                            entry.setState("set")
                            newLines.append(newline)
                            self.backups.append([line, newline])
                            matched = True
                            break
                        elif entry.op == "rm":
                            entry.setState("set")
                            self.backups.append([line, None])
                            matched = True
                            break

                if not matched:
                    newLines.append(line)

            fp.close()

        for entry in self.entries:
            if entry.getState() != "set":
                if entry.op == "add":
                    newline = entry.name + entry.separator + entry.value + "\n"
                    newLines.append(newline)
                    self.backups.append([None, newline])
                    entry.setState("set")

        open(self.fileName, "w").writelines(newLines)

    def replace_line(self, startswith,stanza,always_add=False):
        lines = [ s.strip() for s in open(self.fileName).readlines() ]
        newlines = []
        replaced = False
        for line in lines:
            if re.search(startswith, line):
                if stanza is not None:
                    newlines.append(stanza)
                    self.backups.append([line, stanza])
                replaced = True
            else: newlines.append(line)
        if not replaced and always_add:
            newlines.append(stanza)
            self.backups.append([None, stanza])
        newlines = [ s + '\n' for s in newlines ]
        open(self.fileName,"w").writelines(newlines)

    def replace_or_add_line(self, startswith,stanza):
        return self.replace_line(startswith,stanza,always_add=True)

    def add_lines(self, lines, addToBackup=True):
        fp = open(self.fileName).read(-1)
        sh = re.escape(lines)
        match = re.search(sh, fp, re.MULTILINE)
        if match is not None:
            return

        fp += lines
        open(self.fileName, "w").write(fp)
        self.backups.append([None, lines])

    def replace_lines(self, src, dst, addToBackup=True):
        fp = open(self.fileName).read(-1)
        sh = re.escape(src)
        if dst is None:
            dst = ""
        repl,nums = re.subn(sh, dst, fp)
        if nums <=0:
            return
        open(self.fileName, "w").write(repl)
        if addToBackup:
            self.backups.append([src, dst])

    def append_lines(self, match_lines, append_lines):
        fp = open(self.fileName).read(-1)
        sh = re.escape(match_lines)
        match = re.search(sh, fp, re.MULTILINE)
        if match is None:
            return

        sh = re.escape(append_lines)
        if re.search(sh, fp, re.MULTILINE) is not None:
            return

        newlines = []
        for line in open(self.fileName).readlines():
            if re.search(match_lines, line) is not None:
                newlines.append(line + append_lines)
                self.backups.append([line, line + append_lines])
            else:
                newlines.append(line)

        open(self.fileName, "w").writelines(newlines)

    def backup(self):
        for oldLine, newLine in self.backups:
            if newLine is None:
                self.add_lines(oldLine, False)
            else:
                self.replace_lines(newLine, oldLine, False)
