# * 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 tkinter as tk
from tkinter import *
from tkinter import *
import os, serial
import serial.tools.list_ports
from datetime import datetime
from MT_Commands import *
from Program_Callbacks import *
from File_Check import *
import global_vars
import string


def resource_path(relative_path):
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join('r', os.path.abspath("."), relative_path)


# Write to the Output Display
def update_output(self, message):
    self.Lb3.insert(END, message)
    self.Lb3.yview(END)
    return


# Update the Progress Bar
def bar_update(self, amount):
    self.progress['value'] = amount
    self.update_idletasks()
    return


def check_hex(value):
    for letter in value:
        if letter not in string.hexdigits:
            return True
    return False


# Function to Read from device based on user selection
def read_from_selections(self, ser, total, file_dir_read, file_dir_write):
    error = False
    asterisk = False

    # Check if the file is available
    if not path.exists(file_dir_write):
        update_output(self, "File " + file_dir_write + "was not found")
        error = True

    if not error:
        # Clear the file where info will be written to
        open(file_dir_write, "w").close()
        c_file = open(file_dir_write, "w+")

    # Initialize Variable
    read_content = []

    # Filter the selected entries
    selections = [self.Lb4.get(idx) for idx in self.Lb4.curselection()]

    if not prelim_file_check(self, file_dir_read) and not error:
        if not config_file_format_check(self, file_dir_read):
            # Open the Configuration File and find the items to be read
            read_file = open(file_dir_read, "r")
            for line in read_file.readlines():
                line = ((line.strip('\n')).split(':'))
                for x in range(len(line)):
                    line[x] = line[x].strip()
                if line[0] != ' ' and line[0] != 'NV Region':
                    if selections[0] == 'All Regions':
                        for y in range(1, self.Lb4.size()):
                            if self.Lb4.get(y) not in read_content:
                                read_content.append(self.Lb4.get(y))
                    else:
                        read_content = selections

            # Partition the progress bar based on the number of selections
            if len(read_content) == 0:
                error = True

            if not error:
                # Update the user the procedure is about to begin
                update_output(self, "While in operation this window will be frozen until completion.")
                self.Lb3.insert(END, str(datetime.now()))
                self.Lb3.yview(END)

                value = float(total) / float(len(read_content))
                status = value

                # Grab the max length of NV_Regions to format the output file
                max_width = max(len(filename) for filename in read_content)

                # Create the Header for the file
                c_file.write("NV Region".ljust(max_width + 5) + '%5s %5s %5s %5s %5s' % (
                    ": Item ID    " + "  :", "Sys ID     " + ":", "Sub ID    " + "  :", "Length    " + "  :", "Data" + '\n'))

                # Open the Configuration file to map the information with the NV Regions
                with open(file_dir_read, 'r') as file:
                    for line in file.readlines():
                        line = ((line.strip('\n')).split(':'))
                        for x in range(len(line)):
                            line[x] = line[x].strip()
                        if line[0] != ' ' and line[0] != 'NV Region':
                            if line[0].find('*') != -1:
                                asterisk = True
                            else:
                                asterisk = False
                            for y in range(len(read_content)):
                                wrote = False
                                line[0] = line[0].strip('*')
                                # Check if there is a match between a selection and an item in the Configuration File
                                if read_content[y] == line[0]:
                                    # Separate reads by table and non-table reads
                                    if any(x in line[0] for x in global_vars.nv_multi_page_key_words) and line[1] != ''\
                                            and line[2] != '' and line[3] != '':  # Table Entry
                                        # Find the length of the item
                                        length = sys_nv_length(ser, line[0], line[1], line[2])
                                        # Read the content
                                        sys_nv_read(self, ser, line[0], line[1], line[2], line[3], length, line[4],
                                                    c_file, max_width, asterisk)
                                        wrote = True
                                    else:  # Non-Table Entry
                                        if line[0] != ' ' and line[1] != ' ':
                                            sys_osal_nv_read(self, ser, line[0], line[1], c_file, max_width, asterisk)
                                            wrote = True
                                # If something was written then update the Progress Bar accordingly
                                if wrote:
                                    bar_update(self, status)
                                    status = value + status
                file.close()
        else:
            error = True
    else:
        error = True
    return error


# Function to Write fo a device based on user selection
def write_from_selections(self, ser, total):
    error = False
    # Initialize Lists
    data_entry = []
    nv_region = []

    # Store the content in the Write Frame
    w_list = self.fr_write_back.winfo_children()
    for x in range(len(w_list)):
        if w_list[x].winfo_class() == 'Entry':
            if len(w_list[x].get()) != 0:
                data_entry.append(w_list[x].get().strip())
                nv_region.append(w_list[x - 1].cget("text"))

    if len(nv_region) != 0:
        # Update the user the procedure is about to begin
        update_output(self, "While in operation this window will be frozen until completion.")
        self.Lb3.insert(END, str(datetime.now()))
        self.Lb3.yview(END)

        # Calculating Progress Bar status
        value = float(total) / float(len(nv_region))
        status = value

        with open(global_vars.id_file) as file:
            for line in file.readlines():
                line = ((line.strip('\n')).split(':'))
                for x in range(len(line)):
                    line[x] = line[x].strip()
                for y in range(len(nv_region)):
                    line[0] = line[0].strip("*")
                    if line[0] != '' and nv_region[y] == line[0]:
                        if line[0] != '' and line[1] != '':
                            if data_entry[y].find("0x") != -1:
                                data_entry[y] = data_entry[y][2:]
                            if not (check_hex(data_entry[y])):
                                if int(len(data_entry[y])) % 2 == 0:
                                    entry_length = "{:02x}".format(int(len(data_entry[y]) / 2))
                                    if line[1] == '0x0042':
                                        correct_length = 'f7'
                                    else:
                                        correct_length = sys_osal_nv_length(ser, line[1])
                                    if entry_length == correct_length:
                                        entry_length = "0x" + entry_length
                                        sys_osal_nv_write(self, ser, line[0], line[1], entry_length, data_entry[y])
                                    else:
                                        if line[0].find('NIB') != -1 or line[0].find('nib') != -1:
                                            update_output(self, 'Start the NWK (Tools -> Form Network) and try again.')
                                        else:
                                            update_output(self, 'The length of ' + str(line[0]) +
                                                          ' is not correct.')
                                            update_output(self,'Length should be 0x' + str(correct_length) +
                                                          ' bytes long.')
                                else:
                                    update_output(self, 'The length of ' + str(line[0]) + ' is incorrect.')
                                    update_output(self, 'The value written should be in terms of bytes.')
                                bar_update(self, status)
                                status = value + status
                            else:
                                update_output(self, 'The value of ' + str(line[0]))
                                update_output(self, 'should only contain hexadecimal digits.')
        file.close()
    else:
        update_output(self, "No content to be written to the device.")
        error = True
    return error


# Writing to a device based on file upload
def write_from_file(self, ser, total, file_dir_write):
    # Initialize Variable
    read_content = []
    error = False

    error = prelim_file_check(self, file_dir_write)

    if not write_file_format_check(self, file_dir_write) and not error:
        # Open the file and read the content to be written
        with open(file_dir_write, 'r') as file:
            for line in file.readlines():
                line = ((line.strip('\n')).split(':'))
                for x in range(len(line)):
                    line[x] = line[x].strip()
                line[0] = line[0].strip()
                if line[0] != '' and line[0] != "NV Region":
                    if line[0] not in read_content:
                        read_content.append(line[0])

        # Partition the progress bar based on the number of selections
        value = float(total) / float(len(read_content))
        status = value
    else:
        error = True

    if not error:
        # Update the user the procedure is about to begin
        update_output(self, "While in operation this window will be frozen until completion.")
        self.Lb3.insert(END, str(datetime.now()))
        self.Lb3.yview(END)

        # Open the file and read the content to write
        with open(file_dir_write) as file:
            nv_region = ""
            for line in file.readlines():
                line = ((line.strip('\n')).split(':'))
                for x in range(len(line)):
                    line[x] = line[x].strip()
                if line[0].strip() != '' and line[0] != 'NV Region':
                    line[0] = line[0].strip()
                    # Separate table and non-table entries
                    if any(x in line[0] for x in global_vars.nv_multi_page_key_words):  # Table Entry
                        if line[1].strip() != '' and line[2].strip() != '' and line[3].strip() != '' and \
                                line[4].strip() != '' and line[5].strip() != '':
                            line[0] = line[0].strip('*')
                            if not check_hex(line[5]):
                                # Check if writing was successful
                                updated = sys_nv_update(self, ser, line[0], line[1], line[2], line[3], line[4], line[5])
                                if updated and nv_region != line[0]:
                                    # Update the output that there was a successful write
                                    update_output(self, 'Success: Wrote' + " " + line[0] + " " + 'to Memory')
                            else:
                                update_output(self, 'Failure: Make sure ' + line[0])
                                update_output(self, 'only contains hexadecimal digits')
                                error = True
                            nv_region = line[0]
                    else:  # Non-Table Entry
                        if len(line) >= 4:
                            if line[0] != '' and line[1] != '' and line[2] != '' and line[3] != '':
                                line[0] = line[0].strip('*')
                                if line[0].find('NIB') != -1 or line[0].find('nib') != -1 or line[0].find('group') != -1:  # Initialize the NIB
                                    sys_osal_nv_item_init(self, ser, line[0], line[1])
                                if not check_hex(line[3]):
                                    done = sys_osal_nv_write(self, ser, line[0], line[1], line[2], line[3])
                                    if not done:
                                        if line[0].find('NIB') != -1 or line[0].find('nib') != -1:  # Initialize the NIB
                                            update_output(self, 'Start the NWK (Tools -> Form Network) and try again.')
                                else:
                                    update_output(self, 'Failure: Make sure ' + line[0])
                                    update_output(self, 'only contains hexadecimal digits')
                                    error = True
                        else:
                            update_output(self, "Not enough information in " + os.path.basename(file_dir_write))
                            error = True
                    if not error:
                        # Update the Progress Bar
                        bar_update(self, status)
                        status = value + status
        file.close()
    return error


# Reading Portion of the Cloning Procedure
def clone_content_read(self, ser, total, file_dir_read, file_dir_write):
    error = False

    # Check if the file is available
    if not path.exists(file_dir_write):
        update_output(self, "File " + os.path.basename(file_dir_write) + "was not found")
        error = True

    if not error:
        # Clear the file where info will be written to
        open(file_dir_write, "w").close()
        c_file = open(file_dir_write, "w+")

    if not config_file_format_check(self, file_dir_read) and not error:
        # Initialize List
        read_content = []
        # Open the Configuration File to find the length of the content to be read
        file = open(file_dir_read, "r")
        for line in file.readlines():
            line = ((line.strip('\n')).split(':'))
            for x in range(len(line)):
                line[x] = line[x].strip()
                if line[0] != '' and line[0] != 'NV Region' and line[0][-1] == '*':
                    if line[0] not in read_content:
                        read_content.append(line[0])

        if len(read_content) != 0:
            # Update the user the procedure is about to begin
            update_output(self, "While in operation this window will be frozen until completion.")
            self.Lb3.insert(END, str(datetime.now()))
            self.Lb3.yview(END)

            # Partition the progress bar based on the number of selections
            value = float(total) / float(len(read_content))
            status = value

            # Grab the max length of NV_Regions to format the output file
            max_width = max(len(filename) for filename in read_content)

            # Create the Header for the file
            c_file.write("NV Region".ljust(max_width + 5) + '%5s %5s %5s %5s %5s' % (
                    ": Item ID    " + ":", "Sys ID   " + ":", "Sub ID    " + ":", "Length    " + ":", "Data" + '\n'))

            # Open the Configuration File to read the information of the NV Regions
            file = open(file_dir_read, "r")
            for line in file.readlines():
                line = ((line.strip('\n')).split(':'))
                for x in range(len(line)):
                    line[x] = line[x].strip()
                    # Find items mandatory for cloning
                    if line[0] != '' and line[0] != 'NV Region' and line[0][-1] == '*':
                        # Separate content by table and non-table entries
                        if any(x in line[0] for x in global_vars.nv_multi_page_key_words):  # Table Entry
                            line[0] = line[0].strip('*')
                            if line[0] != ' ' and line[1] != ' ' and line[2] != ' ' and line[3] != ' ':
                                # Find the length of the NV item
                                length = sys_nv_length(ser, line[0], line[1], line[2])
                                # Read the content of the NV item
                                if length != 0 or length != '0':
                                    sys_nv_read(self, ser, line[0], line[1], line[2], line[3], length, line[4], c_file,
                                                max_width, True)
                        else:  # Non-Table Reading
                            line[0] = line[0].strip('*')
                            if line[0] != ' ' and line[1] != ' ':
                                sys_osal_nv_read(self, ser, line[0], line[1], c_file, max_width, True)
                        # Update the Progress bar
                        bar_update(self, status)
                        status = value + status
        else:
            update_output(self, "No data to read from. Check the " + os.path.basename(global_vars.id_file))
            update_output(self, "To clone data make sure the region name ends with a *")
            error = True
    return error


# Writing Portion of the Cloning Procedure
def clone_content_write(self, ser, total, file_dir_write):
    # Initialize List
    read_content = []
    error = False
    error = prelim_file_check(self, file_dir_write)

    if not write_file_format_check(self, file_dir_write):
        # Open the file to know how much content there is to write
        with open(file_dir_write, 'r') as file:
            for line in file.readlines():
                line = ((line.strip('\n')).split(':'))
                for x in range(len(line)):
                    line[x] = line[x].strip()
                line[0] = line[0].strip()
                if line[0] != '' and line[0][-1] == '*':
                    if line[0] not in read_content:
                        read_content.append(line[0])
        file.close()

        # Partition the progress bar based on the number of selections
        value = float(total) / float(len(read_content))
        if total == 50:
            status = 50 + value
        else:
            status = value
    else:
        error = True

    if not error:
        # Open the file to gather the information related to the NV Regions
        with open(file_dir_write) as file:
            nv_region = ""
            for line in file.readlines():
                line = ((line.strip('\n')).split(':'))
                for x in range(len(line)):
                    line[x] = line[x].strip()
                if line[0].strip() != '' and line[0] != 'NV Region' and line[0][-1] == '*':
                    line[0] = line[0].strip()
                    # Separate the content by table and non-table entries
                    if any(x in line[0] for x in global_vars.nv_multi_page_key_words):  # Table Entry
                        if line[1].strip() != '' and line[2].strip() != '' and line[3].strip() != '' \
                                and line[4].strip() != '':
                            line[0] = line[0].strip('*')
                            # Write to the NV region and check if the write was successful
                            if not check_hex(line[5]):
                                updated = sys_nv_update(self, ser, line[0], line[1], line[2], line[3], line[4], line[5])
                                if updated and nv_region != line[0]:
                                    # Update the output display if write was successful
                                    update_output(self, 'Success: Wrote' + " " + line[0] + " " + 'to Memory')
                            else:
                                update_output(self, 'Failure: Make sure ' + line[0])
                                update_output(self, 'only contains hexadecimal digits')
                                error = True
                            nv_region = line[0]
                    else:  # Non-Table Entry
                        if len(line) >= 4:
                            if line[0] != '' and line[1] != '' and line[2] != '' and line[3] != '':
                                line[0] = line[0].strip('*')
                                if line[0].find('NIB') != -1 or line[0].find('nib') != -1:  # Initialize the NIB
                                    sys_osal_nv_item_init(self, ser, line[0], line[1])
                                if not check_hex(line[3]):
                                    sys_osal_nv_write(self, ser, line[0], line[1], line[2], line[3])
                                else:
                                    update_output(self, 'Failure: Make sure ' + line[0])
                                    update_output(self, 'only contains hexadecimal digits')
                                    error = True
                    if not error:
                        # Update the Progress Bar
                        bar_update(self, status)
                        status = value + status
        file.close()
    return status


def start_option(self):
    read_mode = False
    write_mode = False
    error = False
    clone_mode = False

    global_vars.failure_to_write = []

    # Erase the content from the output display
    self.Lb3.delete(0, 'end')

    # Clear the Progress bar
    bar_update(self, 0)

    # Check which application option was selected
    if self.v.get() == 1:  # Only Read
        read_mode = True
        write_mode = False
        clone_mode = False
        total = 100
        read_port = self.Lb1.get(ACTIVE)
        self.Lb2.config(state=tk.DISABLED)

        # Check if all of the input info is available
        if self.Lb1.curselection() is ():
            read_mode = False
            error = True
            update_output(self, 'Please select a COM Port')
            self.Lb1.config(state=tk.NORMAL)
        if self.Lb4.curselection() is ():
            read_mode = False
            error = True
            update_output(self, 'Not all selections have been made yet')

        # Try to Open the Configuration File -> Throw exception if not obtainable
        try:
            f = open(global_vars.id_file)
            file_dir_read = global_vars.id_file
            f.close()
        except IOError:
            update_output(self, os.path.basename(global_vars.id_file) +
                          ' is not in the current directory. Please add the file and re-try.')
            write_mode = False
            read_mode = False
            clone_mode = False
            error = True

        # Try to Open the Content File -> Throw exception if not obtainable
        try:
            f = open(global_vars.content_file)
            file_dir_write = global_vars.content_file
            f.close()
        except IOError:
            update_output(self, os.path.basename(global_vars.content_file) +
                          ' is not in the current directory. Please add the file and re-try.')
            write_mode = False
            read_mode = False
            error = True

    if self.v.get() == 2:  # Only Write
        write_mode = True
        read_mode = False
        clone_mode = False
        total = 100
        write_port = self.Lb2.get(ACTIVE)
        self.Lb1.config(state=tk.DISABLED)

        # Check if a COM port is selected
        if self.Lb2.curselection() is ():
            write_mode = False
            error = True
            update_output(self, 'Select a COM Port')
            self.Lb2.config(state=tk.NORMAL)

        # Open the Content File -> Throw an error if not obtainable
        try:
            f = open(global_vars.content_file)
            file_dir_write = global_vars.content_file
            f.close()
        except IOError:
            update_output(self, os.path.basename(global_vars.content_file) + ' could not be found. '
                                                                             'Please add the file and try again.')
            write_mode = False
            read_mode = False
            error = True

    if self.v.get() == 3:  # Do both Read and Write
        read_mode = True
        write_mode = True
        clone_mode = True
        total = 50
        read_port = self.Lb1.get(ACTIVE)
        write_port = self.Lb2.get(ACTIVE)

        # Check if there are COM Ports selected
        if self.Lb1.curselection() is () or self.Lb2.curselection() is ():
            read_mode = False
            write_mode = False
            clone_mode = False
            error = True
            update_output(self, "Please connect device/s and go to [Tools -> Scan for Devices]")

        # Cross reference the read and write ports
        if read_port == write_port:
            write_mode = False
            read_mode = False
            clone_mode = False
            error = True
            if self.Lb1.curselection() is not () or self.Lb2.curselection() is not ():
                self.Lb3.insert(END, 'Error: Please choose different ports and try again.')
            self.update()
        else:
            write_mode = True
            read_mode = True
            clone_mode = True
            self.Lb1.config(state=tk.DISABLED)
            self.Lb2.config(state=tk.DISABLED)

            # Open the Configuration file -> Throw an exception if not obtainable
            try:
                f = open(global_vars.id_file)
                file_dir_read = global_vars.id_file
                f.close()
            except IOError:
                update_output(self, os.path.basename(global_vars.id_file) +
                              ' is not in current directory. Please add the file and try again.')
                write_mode = False
                read_mode = False
                clone_mode = False
                error = True

            # Open the Content file -> Throw an exception if not obtainable
            try:
                f = open(global_vars.content_file)
                file_dir_write = global_vars.content_file
                f.close()
            except IOError:
                update_output(self, os.path.basename(global_vars.content_file) +
                              ' is not in current directory. Please add the file and try again.')
                write_mode = False
                read_mode = False
                clone_mode = False
                error = True
    # Clear the progress bar
    bar_update(self, 0)

    # Reading Options
    if read_mode and not error:
        # Establishing a Serial Connection
        if sys.platform.startswith('darwin'):
            read_port = "/dev/tty.usbmodemL" + read_port
        try:
            ser = serial.Serial(port=read_port, baudrate=115200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE
                                , bytesize=serial.EIGHTBITS, timeout=1)
        except IOError:
            error = True
            # Erase the content from the output display
            self.Lb3.delete(0, 'end')
            update_output(self, read_port + " is no longer accessible.")
        if not error:
            number_of_items = 0
            if clone_mode:
                error = clone_content_read(self, ser, total, file_dir_read, file_dir_write)
            else:
                error = read_from_selections(self, ser, total, file_dir_read, file_dir_write)

            # Enable the Start Option in Menu Bar upon selection
            self.view_menu.entryconfig(0, state=NORMAL)

            # Enable the READ COM Port and the Reading Frame Content
            self.Lb1.config(state=tk.NORMAL)
            self.Lb4.config(state=tk.NORMAL, bd=0)

            ser.close()
            # Update the output display
            if not error:
                update_output(self, 'Read Complete. Go to [View -> Read File] to see content')

    # Writing Options
    if write_mode and not error:
        # Establishing a Serial Connection
        if sys.platform.startswith('darwin'):
            write_port = "/dev/tty.usbmodemL" + write_port
        try:
            ser = serial.Serial(port=write_port, baudrate=115200, parity=serial.PARITY_NONE,
                                stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, rtscts=True, timeout=1)
        except IOError:
            # Erase the content from the output display
            error = True
            self.Lb3.delete(0, 'end')
            update_output(self, write_port + " is no longer accessible.")

        if not error:
            # Segment "Cloning" and "Writing to the device"
            if clone_mode:
                clone_content_write(self, ser, total, file_dir_write)
            else:
                # Check the status of the Checkbox
                if self.w.get() == '1':  # User choose to write from a file:
                    error = write_from_file(self, ser, total, file_dir_write)
                else:  # User choose to write to the device from their inputs
                    error = write_from_selections(self, ser, total)

            # Enable the WRITE COM Port
            self.Lb2.config(state=tk.NORMAL)

            # Enable the Start Option in Menu Bar upon selection
            self.view_menu.entryconfig(0, state=NORMAL)

            ser.flushInput()
            ser.flushOutput()
            ser.close()

    # Update the user the procedure is complete
    if not error:
        if clone_mode:
            update_output(self, 'Please Power Cycle/Restart the new ZC to complete the procedure.')
            update_output(self, 'Ensure to do a physical reset if it is the first time restarting the device after')
            update_output(self, 'programming with an XDS110. If using a LaunchPad the reset button may be pressed.')
            # Update user on window status
            self.Lb3.insert(END, str(datetime.now()))
            self.Lb3.yview(END)
            update_output(self, "Window is now operational.")
            self.Lb3.yview(END)
        else:
            if self.w.get() == '1':
                update_output(self, 'If cloning to a new ZC, then power cycle/restart the device to complete the procedure.')
                update_output(self, 'Ensure to do a physical reset if it is the first time restarting the device after')
                update_output(self, 'programming with an XDS110. If using a LaunchPad the reset button may be pressed.')
                # Update user on window status
                self.Lb3.insert(END, str(datetime.now()))
                self.Lb3.yview(END)
                # Update the output display
                update_output(self, "Window is now operational.")
            else:
                # Update user on window status
                self.Lb3.insert(END, str(datetime.now()))
                self.Lb3.yview(END)
                # Update the output display
                update_output(self, "Procedure finished. Window is now operational.")
    return
