# * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
#  *
#  *
#  *  Redistribution and use in source and binary forms, with or without
#  *  modification, are permitted provided that the following conditions
#  *  are met:
#  *
#  *    Redistributions of source code must retain the above copyright
#  *    notice, this list of conditions and the following disclaimer.
#  *
#  *    Redistributions in binary form must reproduce the above copyright
#  *    notice, this list of conditions and the following disclaimer in the
#  *    documentation and/or other materials provided with the
#  *    distribution.
#  *
#  *    Neither the name of Texas Instruments Incorporated nor the names of
#  *    its contributors may be used to endorse or promote products derived
#  *    from this software without specific prior written permission.
#  *
#  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
#  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
#  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
#  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
#  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
#  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#  *
# */
import os
from os import path
from tkinter import *
import global_vars


def file_in_path(self, file):
    error = False
    if not path.exists(file):
        error = True
    return error


def prelim_file_check(self,  file):
    error = False

    # Check if the file is available
    if not path.exists(file):
        # Erase the content from the output display
        self.Lb3.delete(0, 'end')
        self.Lb3.insert(END, "File " + os.path.basename(file) + " was not found. Place file in directory and re-try.")
        self.Lb3.yview(END)
        error = True

    # Check if the file is empty
    if not error:
        with open(file, 'r') as f:
            first_char = f.read(1)
        f.close()
        if len(first_char.strip()) == 0:
            # Erase the content from the output display
            self.Lb3.delete(0, 'end')
            self.Lb3.insert(END, "No Content to be read in " + str(os.path.basename(file)))
            self.Lb3.yview(END)
            error = True
    return error


def max_width_file(self, content):
    name = []
    for x in content:
        line = ((x.strip('\n')).split(':'))
        line[0] = line[0].strip()
        if line[0].find("NV Region") == -1:
            name.append(line[0])

    # Grab the max length of NV_Regions to format the output file
    if len(name) != 0:
        max_width = max(len(filename) for filename in name)
    else:
        max_width = 0
    return max_width


def table_add(name):
    name = name.strip('*')
    global_vars.nv_multi_page_key_words.append(name)
    res = []
    for i in global_vars.nv_multi_page_key_words:
        if i not in res:
            res.append(i)
    global_vars.nv_multi_page_key_words=res
    return


# Check the format of the configuration file
def config_file_format_check(self, file_config):
    # The configuration file should be in a specific format
    error = False

    config_file = open(file_config, "r+")

    first_line = 0
    no_header = False

    content = config_file.readlines()
    max_width = max_width_file(self, content)

    for line in content:
        line = line.strip()

    # Check the content in the file
    if len(content) != 0:
        for lines in content:
            if not error:
                line = lines.strip("\n")
                if len(line.strip()) != 0 and line.find(":") == -1:
                    error = True
                    self.Lb3.delete(0, 'end')
                    self.Lb3.insert(END, "The file " + os.path.basename(file_config) + " is not in the correct format.")
                    self.Lb3.insert(END, "Make sure to include a separator between row information.")
                    self.Lb3.yview(END)
                else:
                    line = line.split(":")
                    if len(line) != 0:
                        if len(line) == 5:
                            if line[0] != 'NV Region':
                                table_add(line[0])
                                # Check the ID
                                if line[1].find('0x') != -1 and len(line[1].strip()) == 6:
                                    # Check the System ID
                                    if line[2].find('0x') != -1 and len(line[2].strip()) == 4:
                                        # Check the Sub ID
                                        if line[3].find('0x') != -1 and len(line[3].strip()) == 6:
                                            # Check the number of entries
                                            if not (str(line[4]).strip()).isdigit():
                                                error = True
                                                self.Lb3.delete(0, 'end')
                                                self.Lb3.insert(END, "The entry value for " + line[0] + " is incorrect.")
                                        else:
                                            error = True
                                            self.Lb3.delete(0, 'end')
                                            self.Lb3.insert(END,
                                                            "The Sub ID of " + line[0] + " is not in the correct format.")
                                            self.Lb3.insert(END, "Make sure it is 0x followed by a four digit value.")
                                    else:
                                        error = True
                                        self.Lb3.delete(0, 'end')
                                        self.Lb3.insert(END,
                                                        "The System ID of " + line[0] + " is not in the correct format.")
                                        self.Lb3.insert(END, "Make sure it is 0x followed by a two digit value.")
                                else:
                                    error = True
                                    self.Lb3.delete(0, 'end')
                                    self.Lb3.insert(END, "The Item ID of " + line[0] + " is not in the correct format.")
                                    self.Lb3.insert(END, "Make sure it is 0x followed by a four digit value.")
                        if len(line) == 2:
                            if line[0] != 'NV Region' and len(line[0].strip()) != 0:
                                # Check the ID
                                if line[1].find('0x') == -1 or len(line[1].strip()) != 6:
                                    error = True
                                    self.Lb3.delete(0, 'end')
                                    self.Lb3.insert(END, "The Item ID of " + line[0] + " is not in the correct format.")
                        if len(line) == 3 or len(line) == 4 or len(line) > 5:
                            error = True
                            self.Lb3.delete(0, 'end')
                            self.Lb3.insert(END, "There was not enough/too much information provided for: ")
                            self.Lb3.insert(END, line[0])
                    else:
                        error = True

    # Create the Header for the file if there is none
    if not error:
        for lines in content:
            # There is a problem with the header
            line = lines.strip("\n")
            if first_line == 0:
                if line.find("NV Region") == -1 or line.find("Item ID") == -1 or line.find("Sys ID") == -1\
                        or line.find("Sub ID") == -1 or line.find("Entries") == -1:
                    config_file.truncate(0)
                    config_file.seek(0,0)
                    config_file.write("NV Region:".ljust(max_width+4) + '%5s %5s %5s %5s' % (
                        "Item ID:  ", "Sys ID: ", "Sub ID: ", "Entries" + '\n'))
                    no_header = True
            first_line = 1
        if no_header:
            for x in content:
                line = (x.strip('\n'))
                config_file.write(line + '\n')
    return error


# Check the format of the file that content will be written from
def write_file_format_check(self, write_file):
    # The configuration file should be in a specific format
    error = False

    if not prelim_file_check(self, write_file):
        # Check if the file is a text file
        if os.path.basename(write_file).endswith('.txt'):
            # Safe to open the file
            config_file = open(write_file, "r+")
        else:
            error = True
            self.Lb3.insert(END, "The file chosen did not have the correct extension.")
    else:
        error = True

    line = []
    if not error:
        first_line = 0
        no_header = False

        content = config_file.readlines()
        max_width = max_width_file(self, content)

        # Check the content in the file
        if len(content) != 0:
            for lines in content:
                if not error:
                    line = lines.strip("\n")
                    if len(line.strip()) != 0 and line.find(":") == -1:
                        error = True
                        self.Lb3.delete(0, 'end')
                        self.Lb3.insert(END,
                                        "The file " + os.path.basename(write_file) + " is not in the correct format.")
                        self.Lb3.insert(END, "Make sure to include a separator between row information.")
                        self.Lb3.yview(END)
                    else:
                        line = line.split(":")
                        if len(line) != 0:
                            if len(line) == 6:
                                if line[0].strip() != 'NV Region':
                                    line[0]= line[0].strip()
                                    table_add(line[0])
                                    # Check the ID
                                    if line[1].find('0x') != -1 and len(line[1].strip()) == 6:
                                        # Check the System ID
                                        if line[2].find('0x') != -1 and len(line[2].strip()) == 4:
                                            # Check the Sub ID
                                            if line[3].find('0x') != -1 and len(line[3].strip()) == 6:
                                                # Check the Length
                                                if line[4].find('0x') != -1 and (len(line[4].strip()) == 4 or
                                                                                 len(line[4].strip()) == 5):
                                                    # Check the Data
                                                    if (int(len(line[5].strip()) / 2)) != (int(line[4].strip(), 16)):
                                                        error = True
                                                        self.Lb3.delete(0, 'end')
                                                        self.Lb3.insert(END, "The data value for " + line[0] +
                                                                        " does not match the length value specified.")
                                                else:
                                                    error = True
                                                    self.Lb3.delete(0, 'end')
                                                    self.Lb3.insert(END,
                                                                    "The length value for " + line[0] +
                                                                    " should be two characters long.")
                                            else:
                                                error = True
                                                self.Lb3.delete(0, 'end')
                                                self.Lb3.insert(END,
                                                                "The Sub ID of " + line[
                                                                    0] + " is not in the correct format.")
                                                self.Lb3.insert(END, "Make sure it is 0x followed by a four digit value.")
                                        else:
                                            error = True
                                            self.Lb3.delete(0, 'end')
                                            self.Lb3.insert(END,"The System ID of " + line[0] +
                                                            " is not in the correct format.")
                                            self.Lb3.insert(END, "Make sure it is 0x followed by a two digit value.")
                                    else:
                                        error = True
                                        self.Lb3.delete(0, 'end')
                                        self.Lb3.insert(END,
                                                        "The Item ID of " + line[0] + " is not in the correct format.")
                                        self.Lb3.insert(END, "Make sure it is 0x followed by a four digit value.")
                            if len(line) == 4:
                                if line[0].strip() != 'NV Region' and len(line[0].strip()) != 0:
                                    # Check the ID
                                    if line[1].find('0x') != -1 and len(line[1].strip()) == 6:
                                        # Check the Length
                                        if line[2].find('0x') != -1 and (len(line[2].strip()) == 4 or
                                                                         len(line[2].strip()) == 5 or
                                                                         len(line[2].strip()) == 6):
                                            # Check the Data
                                            if (int(len(line[3].strip()) / 2)) != (int(line[2].strip(), 16)):
                                                error = True
                                                self.Lb3.delete(0, 'end')
                                                self.Lb3.insert(END, "The data value for " + line[0] +
                                                                " does not match the length value specified.")
                                        else:
                                            error = True
                                            self.Lb3.delete(0, 'end')
                                            self.Lb3.insert(END,
                                                            "The length value for " + line[0] +
                                                            " should be two characters long.")
                                    else:
                                        error = True
                                        self.Lb3.delete(0, 'end')
                                        self.Lb3.insert(END, "The Item ID of " + line[0] +
                                                        " is not in the correct format.")
                            if len(line) >1 and (len(line) == 5 or len(line) > 6):
                                error = True
                                self.Lb3.delete(0, 'end')
                                self.Lb3.insert(END, "There was not enough/ too much information provided for: ")
                                self.Lb3.insert(END, line[0])
                        else:
                            error = True

        # Create the Header for the file if there is none
        if not error:
            for lines in content:
                # There is a problem with the header
                line = lines.strip("\n")
                if first_line == 0:
                    if line.find("NV Region") == -1 or line.find("Item ID") == -1 or line.find("Sub ID") \
                            == -1 or line.find("Length") == -1 or line.find("Data") == -1:
                        config_file.truncate(0)
                        config_file.seek(0, 0)
                        config_file.write("NV Region" + '%5s %5s %5s %5s' % (
                            ": Item ID    " + ":", "Sub ID    " + ":", "Length" + ":", "Data" + ":" + '\n'))
                        no_header = True
                first_line = 1
            if no_header:
                for x in content:
                    line = (x.strip('\n'))
                    config_file.write(line + '\n')
    return error


# Check the format of the file that will be loaded from
def load_config_file_format_check(self, load_config_file):
    # Check if the file is available
    if not path.exists(load_config_file):
        self.Lb3.insert(END, "File " + os.path.basename(load_config_file) + "was not found")
        self.Lb3.yview(END)
        error = True

    config_id_file = (load_config_file.strip('.txt') + '_ID') + '.txt'

    # Check if the configuration file is available
    if not path.exists(config_id_file):
        self.Lb3.insert(END, "File " + os.path.basename(load_config_file) + "was not found")
        self.Lb3.yview(END)
        error = True

    # Check if the file is empty
    if not error:
        # Check the config file is okay
        if config_file_format_check(self, load_config_file):
            error = True

    # Check the load settings file
    if not error:
        # Save the content in the file
        with open(load_config_file, 'r') as file:
            lines = file.readlines()
        file.close()

        # Check the application
        if lines[0] != ' ':
            app_choice = int(lines[0].strip())
            if app_choice != (0 or 1 or 2 or 3):
                error = True
                self.Lb3.insert(END, "Error in the file loaded. Please check the format")
                self.Lb3.yview(END)

        # Check the read port
        if not error:
            if lines[1] != ' ':
                port = lines[1].strip()
                if port.find("COM") == -1:
                    error = True
                    self.Lb3.insert(END, "Error in the file loaded. Please check the format")

        # Check the write port
        if not error:
            if lines[2] != ' ':
                port = lines[2].strip()
                if port.find("COM") == -1:
                    error = True
                    self.Lb3.insert(END, "Error in the file loaded. Please check the format")
    return error
