#!python
""" ups-monitor  -  Displays current status of all active UPSs

    A utility to give the current state of all compatible UPSs. The default behavior
    is to continuously update a text based table in the current window until Ctrl-C is
    pressed.  With the *--gui* option, a table of relevant parameters will be updated
    in a Gtk window.  You can specify the delay between updates with the *--sleep N*
    option where N is an integer > 10 that specifies the number of seconds to sleep
    between updates.  The *--log* option is used to write all monitor data to a psv log
    file.  When writing to a log file, the utility will indicate this in red at the top of
    the window with a message that includes the log file name.  The *--status* option will
    output a table of the current status.  The *--long* option will include additional
    informational parameters. By default, unresponsive UPSs will not be displayed, but the
    *--show_unresponsive* can be used to force their display.

    Copyright (C) 2019  RicksLab

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
"""
__author__ = 'RueiKe'
__copyright__ = 'Copyright (C) 2019 RicksLab'
__credits__ = ['']
__license__ = 'GNU General Public License'
__program_name__ = 'ups-monitor'
__maintainer__ = 'RueiKe'
__docformat__ = 'reStructuredText'
# pylint: disable=multiple-statements
# pylint: disable=line-too-long
# pylint: disable=bad-continuation

import argparse
import threading
import os
import sys
import re
import time
import logging
from typing import TextIO, List, Any, Callable
try:
    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import GLib, Gtk
except ModuleNotFoundError as error:
    print('gi import error: {}'.format(error))
    print('gi is required for %s', __program_name__)
    print('   In a venv, first install vext:  pip install --no-cache-dir vext')
    print('   Then install vext.gi:  pip install --no-cache-dir vext.gi')
    sys.exit(0)
from UPSmodules import UPSmodule as UPS
from UPSmodules import env
from UPSmodules import UPSgui
from UPSmodules import __version__, __status__

set_gtk_prop = UPSgui.GuiProps.set_gtk_prop
LOGGER = logging.getLogger('ups-utils')
MAX_WIDTH = 23


class MonitorWindow(Gtk.Window):
    """
    Class defining Monitor Window
    """
    def __init__(self, ups: UPS.UPSsnmp, non_mib_params: list, mib_params: list, devices: dict):
        """ Initialize the main UPS monitor window.

        :param ups:  The main ups module object
        :param non_mib_params:  A list of non-mib parameters
        :param mib_params:  A list of mib parameter results
        :param devices: A dictionary of Gtk components and values
        """
        self.quit = False

        # RuntimeError: Gtk couldn't be initialized. Use Gtk.init_check() if you want to handle this case.
        Gtk.Window.__init__(self, title='{} - Monitor'.format(env.UT_CONST.gui_window_title))
        init_chk_value = Gtk.init_check(sys.argv)
        LOGGER.debug('init_check: %s', init_chk_value)
        if not init_chk_value[0]:
            print('Gtk Error, Exiting')
            sys.exit(-1)
        self.set_border_width(0)
        UPSgui.GuiProps.set_style()

        icon_file = os.path.join(env.UT_CONST.icon_path, env.UtConst.gui_monitor_icon_file)
        LOGGER.debug('Icon file: [%s]', icon_file)
        if os.path.isfile(icon_file):
            self.set_icon_from_file(icon_file)

        grid = Gtk.Grid()
        self.add(grid)

        col = 0
        row = 0
        num_ups = ups.get_num_ups_tuple()[0] if env.UT_CONST.show_unresponsive else ups.get_num_ups_tuple()[3]

        # Set logging details at top of table if logging enabled
        if LOGGER.getEffectiveLevel() == logging.DEBUG:
            log_label = Gtk.Label(name='warn_label')
            log_label.set_markup('<big><b> DEBUG Logger Active </b></big>')
            lbox = Gtk.Box(spacing=6, name='warn_box')
            set_gtk_prop(log_label, top=1, bottom=1, right=1, left=1)
            lbox.pack_start(log_label, True, True, 0)
            grid.attach(lbox, 0, row, num_ups + 1, 1)
        row += 1
        if env.UT_CONST.LOG:
            log_label = Gtk.Label(name='warn_label')
            log_label.set_markup('<big><b> Logging to:    </b>' + env.UT_CONST.log_file + '</big>')
            lbox = Gtk.Box(spacing=6, name='warn_box')
            set_gtk_prop(log_label, top=1, bottom=1, right=1, left=1)
            lbox.pack_start(log_label, True, True, 0)
            grid.attach(lbox, 0, row, num_ups + 1, 1)
        row += 1
        row_start = row

        # Set first column of table to static values
        row = row_start
        row_labels = {'display_name': Gtk.Label(name='white_label')}
        row_labels['display_name'].set_markup('<b>UPS Parameters</b>')
        # Set row labels for header items
        for v in non_mib_params:
            row_labels[v] = Gtk.Label(name='white_label')
            row_labels[v].set_markup('<b>' + str(ups.get_mib_name(v)) + '</b>')
        # Set row labels for command items
        for v in mib_params:
            row_labels[v] = Gtk.Label(name='white_label')
            row_labels[v].set_markup('<b>' + str(ups.get_mib_name(v)) + '</b>')
        # Set boxes for each row label
        for row_label_item in row_labels.values():
            lbox = Gtk.Box(spacing=6, name='head_box')
            set_gtk_prop(lbox, top=1, bottom=1, right=1, left=1)
            set_gtk_prop(row_label_item, top=1, bottom=1, right=4, left=4, align=(0.0, 0.5))
            lbox.pack_start(row_label_item, True, True, 0)
            grid.attach(lbox, col, row, 1, 1)
            row += 1

        # Associate all table items with data source in devices dictionary
        col = 1
        def_box_css = "{ background-image: image(%s); }" % UPSgui.GuiProps.color_name_to_hex('slate_md')
        for item_name, item_ups in ups.get_ups_list(errups=env.UT_CONST.show_unresponsive).items():
            row = row_start
            devices[item_ups['uuid']] = {'display_name': {
                'label': Gtk.Label(label=ups.ups_name(item_ups), name='white_label'),
                'box': Gtk.Box(spacing=6, name='head_box'),
                'box_name': 'head_box'}}
            lbox = devices[item_ups['uuid']]['display_name']['box']
            litem = devices[item_ups['uuid']]['display_name']['label']
            set_gtk_prop(lbox, top=1, bottom=1, right=1, left=1)
            set_gtk_prop(litem, top=1, bottom=1, right=3, left=3, width_chars=17)
            set_gtk_prop(litem, width_chars=MAX_WIDTH)
            lbox.pack_start(litem, True, True, 0)
            grid.attach(lbox, col, row, 1, 1)
            row += 1
            for item_hdr in non_mib_params:
                box_name = '{}_{}'.format(item_name, item_hdr)
                devices[item_ups['uuid']].update({item_hdr: {'label': '', 'box': '', 'box_name': box_name}})
                UPSgui.GuiProps.set_style(css_str="#{} {}".format(box_name, def_box_css))
                devices[item_ups['uuid']][item_hdr]['label'] = Gtk.Label(
                    label=ups.get_ups_parameter_value(item_hdr, item_ups), name='white_label')
                devices[item_ups['uuid']][item_hdr]['label'].set_width_chars(10)
                devices[item_ups['uuid']][item_hdr]['box'] = Gtk.Box(spacing=6, name=box_name)
                lbox = devices[item_ups['uuid']][item_hdr]['box']
                litem = devices[item_ups['uuid']][item_hdr]['label']
                set_gtk_prop(lbox, top=1, bottom=1, right=1, left=1)
                set_gtk_prop(litem, top=1, bottom=1, right=3, left=3, width_chars=17)
                set_gtk_prop(litem, width_chars=MAX_WIDTH)
                lbox.pack_start(litem, True, True, 0)
                grid.attach(lbox, col, row, 1, 1)
                row += 1
            for item_cmd in mib_params:
                box_name = '{}_{}'.format(item_name, item_cmd)
                devices[item_ups['uuid']].update({item_cmd: {'label': '', 'box': '', 'box_name': box_name}})
                UPSgui.GuiProps.set_style(css_str="#{} {}".format(box_name, def_box_css))
                devices[item_ups['uuid']][item_cmd]['label'] = Gtk.Label(
                    label=ups.get_ups_parameter_value(item_cmd, item_ups), name='white_label')
                devices[item_ups['uuid']][item_cmd]['label'].set_width_chars(10)
                devices[item_ups['uuid']][item_cmd]['box'] = Gtk.Box(spacing=6, name=box_name)
                lbox = devices[item_ups['uuid']][item_cmd]['box']
                litem = devices[item_ups['uuid']][item_cmd]['label']
                set_gtk_prop(lbox, top=1, bottom=1, right=1, left=1)
                set_gtk_prop(litem, top=1, bottom=1, right=3, left=3, width_chars=17)
                set_gtk_prop(litem, width_chars=MAX_WIDTH)
                lbox.pack_start(litem, True, True, 0)
                grid.attach(lbox, col, row, 1, 1)
                row += 1
            col += 1
        if LOGGER.getEffectiveLevel() == logging.DEBUG:
            log_message = ''
            for k, v in devices.items():
                if log_message: log_message = '{}\n\n{}:'.format(log_message, k)
                else: log_message = '{}:\n\n'.format(k)
                for k2, v2 in v.items():
                    log_message = '{}\n    {}:{}'.format(log_message, k2, v2)
            LOGGER.debug('Device dict:\n %s', log_message)

    def set_quit(self, _arg2: Any, _arg3: Any) -> None:
        """ Function called when quit monitor is executed.  Sets flag to end update loop.

        :param _arg2: Ignored
        :param _arg3: Ignored
        :return: None
        """
        self.quit = True


def update_data(ups: UPS.UPSsnmp, header_list: list, command_list: list, devices: dict) -> None:
    """ Function that updates data in MonitorWindow  with call to read data from ups.

    :param ups:  The main ups module object
    :param header_list:  A list of non-mib parameters
    :param command_list:  A list of mib parameter results
    :param devices: A dictionary of Gtk components and values
    :return: None
    """
    ups_data = ups.read_all_ups_list_items(command_list, errups=env.UT_CONST.show_unresponsive)
    if env.UT_CONST.LOG:
        print_log(env.UT_CONST.log_file_ptr, header_list, command_list, ups_data)

    # update gui
    for dev_uuid, dev_data in devices.items():
        ups_name = ups.get_name_for_ups_uuid(dev_uuid)
        if not ups_data[ups_name]['valid']:
            state_style = UPS.UPSsnmp.state_style.warn
            mib_name = 'mib_system_status'
            gui_comp = dev_data[mib_name]
            lv = gui_comp['label']
            box_name = gui_comp['box_name']
            lv.set_markup('<b>{}</b>'.format('Unresponsive'))
            UPSgui.GuiProps.set_style(css_str="#%s { background-image: image(%s); }" % (
                box_name, UPSgui.GuiProps.color_name_to_hex('yellow')))
            continue
        for mib_name, gui_comp in dev_data.items():
            state_style = UPS.UPSsnmp.state_style.normal
            data_value = str(ups_data[ups_name][mib_name])[:MAX_WIDTH]
            lv = gui_comp['label']
            box_name = gui_comp['box_name']
            if data_value == '-1':
                data_value = ''
            if mib_name == 'mib_battery_capacity' and data_value.isnumeric():
                if int(data_value) <= ups.daemon_params['threshold_battery_capacity']['crit']:
                    state_style = UPS.UPSsnmp.state_style.crit
                elif int(data_value) <= ups.daemon_params['threshold_battery_capacity']['warn']:
                    state_style = UPS.UPSsnmp.state_style.warn
            elif mib_name == 'mib_output_load' and data_value.isnumeric():
                if int(data_value) >= ups.daemon_params['threshold_battery_load']['crit']:
                    state_style = UPS.UPSsnmp.state_style.crit
                elif int(data_value) >= ups.daemon_params['threshold_battery_load']['warn']:
                    state_style = UPS.UPSsnmp.state_style.warn
            elif mib_name == 'mib_battery_status':
                if re.match(env.UT_CONST.PATTERNS['NORMAL'], data_value):
                    state_style = UPS.UPSsnmp.state_style.green
                else:
                    state_style = UPS.UPSsnmp.state_style.crit
            elif mib_name == 'mib_system_status':
                if re.match(env.UT_CONST.PATTERNS['ONLINE'], data_value):
                    state_style = UPS.UPSsnmp.state_style.green
                else:
                    state_style = UPS.UPSsnmp.state_style.crit
            elif mib_name == 'display_name':
                state_style = UPS.UPSsnmp.state_style.bold

            set_gtk_prop(lv, width_chars=MAX_WIDTH+1)
            if state_style == UPS.UPSsnmp.state_style.crit:
                lv.set_markup('<b>{}</b>'.format(data_value))
                UPSgui.GuiProps.set_style(css_str="#%s { background-image: image(%s); }" % (
                    box_name, UPSgui.GuiProps.color_name_to_hex('red')))
            elif state_style == UPS.UPSsnmp.state_style.warn:
                lv.set_markup('<b>{}</b>'.format(data_value))
                UPSgui.GuiProps.set_style(css_str="#%s { background-image: image(%s); }" % (
                    box_name, UPSgui.GuiProps.color_name_to_hex('yellow')))
            elif state_style == UPS.UPSsnmp.state_style.green:
                lv.set_markup('<b>{}</b>'.format(data_value))
                UPSgui.GuiProps.set_style(css_str="#%s { background-image: image(%s); }" % (
                    box_name, UPSgui.GuiProps.color_name_to_hex('green_dk')))
            elif state_style == UPS.UPSsnmp.state_style.bold:
                lv.set_markup('<b>{}</b>'.format(data_value))
            else:
                lv.set_text(data_value)

    while Gtk.events_pending():
        Gtk.main_iteration_do(True)


def refresh(refresh_time: int, updater: Callable, ups: UPS.UPSsnmp, header_list: list,
            command_list: list, devices: dict, umonitor: MonitorWindow) -> None:
    """ Function that continuously updates the Gtk monitor window.

    :param refresh_time:  Delay time in seconds between monitor display refreshes
    :param updater: Function name that does the actual refresh of the monitor table.
    :param ups:  The main ups module object
    :param header_list:  A list of non-mib parameters
    :param command_list:  A list of mib parameter results
    :param devices: A dictionary of Gtk components and values
    :param umonitor: The main Gtk monitor window.
    :return: None
    """
    while True:
        if umonitor.quit:
            print('Quitting...')
            Gtk.main_quit()
            sys.exit(0)
        GLib.idle_add(updater, ups, header_list, command_list, devices)
        for _sleep_cnt in range(0, refresh_time):
            if umonitor.quit:
                print('Quitting...')
                Gtk.main_quit()
                sys.exit(0)
            time.sleep(1)


def print_monitor_table(ups: UPS.UPSsnmp, header_list: list, cmd_list: list, ups_data: dict) -> int:
    """ Print the monitor table in format optimized for terminal window.

    :param ups:  The main ups module object
    :param header_list:  A list of non-mib parameters
    :param cmd_list:  A list of mib parameter results
    :param ups_data: A dictionary of results for items listed in header and command lists
    :return: Zero if all is good.
    """
    num_ups = ups.get_num_ups_tuple()
    if num_ups[0] < 1:
        return -1

    hrw = 29  # Row header item width
    irw = MAX_WIDTH + 1  # Row data item width

    print('┌', '─'.ljust(hrw, '─'), sep='', end='')
    for _, _ in ups_data.items():
        print('┬', '─'.ljust(irw, '─'), sep='', end='')
    print('┐')

    print('│', '\x1b[1;36m' + 'UPS Parameters'.ljust(hrw, ' ') + '\x1b[0m', sep='', end='')
    for value in ups_data.values():
        print('│', '\x1b[1;36m' + value['display_name'].ljust(irw, ' ') + '\x1b[0m',
              sep='', end='')
    print('│')

    print('├', '─'.ljust(hrw, '─'), sep='', end='')
    for _, _ in ups_data.items():
        print('┼', '─'.ljust(irw, '─'), sep='', end='')
    print('┤')

    for info_item in header_list:
        print('│', '\x1b[1;36m' + info_item.ljust(hrw, ' ')[:hrw] + '\x1b[0m',
              sep='', end='')
        for values in ups_data.values():
            print('│', str(values[info_item]).ljust(irw, ' ')[:irw], sep='', end='')
        print('│')
    for table_item in cmd_list:
        print('│', '\x1b[1;36m' + ups.get_mib_name_for_type(table_item, 'apc-ap9630').ljust(hrw, ' ')[:hrw] + '\x1b[0m',
              sep='', end='')
        for value in ups_data.values():
            if table_item == 'mib_system_status':
                if re.match(env.UT_CONST.PATTERNS['ONLINE'], value[table_item]):
                    item_str = '\x1b[1;30;42m' + value[table_item].ljust(irw, ' ')[:irw] + '\x1b[0m'
                else:
                    item_str = '\x1b[1;37;41m' + value[table_item].ljust(irw, ' ')[:irw] + '\x1b[0m'
            elif table_item == 'mib_battery_status':
                if re.match(env.UT_CONST.PATTERNS['NORMAL'], value[table_item]):
                    item_str = '\x1b[1;30;42m' + value[table_item].ljust(irw, ' ')[:irw] + '\x1b[0m'
                else:
                    item_str = '\x1b[1;37;41m' + value[table_item].ljust(irw, ' ')[:irw] + '\x1b[0m'
            else:
                item_str = str(value[table_item]).ljust(irw, ' ')[:irw]
            print('│', item_str, sep='', end='')
        print('│')

    print('└', '─'.ljust(hrw, '─'), sep='', end='')
    for _ in ups_data.keys():
        print('┴', '─'.ljust(irw, '─'), sep='', end='')
    print('┘')
    return 0


def print_log(fileptr: TextIO, header_list: list, command_list: list, ups_data: dict) -> None:
    """ Print the logfile data line.

    :param fileptr:  The logfile fileptr
    :param header_list:  A list of non-mib parameters
    :param command_list:  A list of mib parameter results
    :param ups_data: A dictionary of results for items listed in header and command lists
    :return: None
    """
    time_str = (str(env.UT_CONST.now(ltz=True).strftime('%c')).strip())
    for values in ups_data.values():
        print('{}'.format(time_str), file=fileptr, end='')
        for item in header_list:
            print('|{}'.format(values[item]), file=fileptr, end='')
        for item in command_list:
            print('|{}'.format(values[item]), file=fileptr, end='')
        print('', file=fileptr)


def print_log_header(fileptr: TextIO, header_list: List[str], command_list: list) -> None:
    """ Print the logfile header line.

    :param fileptr:  The logfile fileptr
    :param header_list:  A list of non-mib parameters
    :param command_list:  A list of mib parameter results
    :return: None
    """
    print('time', file=fileptr, end='')
    for item in header_list:
        print('|{}'.format(item), file=fileptr, end='')
    for item in command_list:
        print('|{}'.format(item), file=fileptr, end='')
    print('', file=fileptr)


def main() -> None:
    """
    Main function

    :return: None
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('--about', help='README', action='store_true', default=False)
    parser.add_argument('--status', help='Display table of current status of UPSs', action='store_true', default=False)
    parser.add_argument('--long', help='Include static items', action='store_true', default=False)
    parser.add_argument('--show_unresponsive', help='Display unresponsive UPSs', action='store_true', default=False)
    parser.add_argument('--gui', help='Display GTK Version of Monitor', action='store_true', default=False)
    parser.add_argument('--log', help='Write all monitor data to logfile', action='store_true', default=False)
    parser.add_argument('--sleep', help='Number of seconds to sleep between updates',
                        type=int, default=UPS.UPSsnmp.daemon_param_defaults['read_interval']['monitor'])
    parser.add_argument('-d', '--debug', help='Debug output', action='store_true', default=False)
    args = parser.parse_args()

    # About me
    if args.about:
        print(__doc__)
        print('Author: ', __author__)
        print('Copyright: ', __copyright__)
        print('Credits: ', __credits__)
        print('License: ', __license__)
        print('Version: ', __version__)
        print('Maintainer: ', __maintainer__)
        print('Status: ', __status__)
        sys.exit(0)

    env.UT_CONST.set_env_args(args, __program_name__)
    LOGGER.debug('########## %s %s', __program_name__, __version__)

    if not env.UT_CONST.check_env():
        env.UT_CONST.log_print('Error in environment. Exiting...')
        sys.exit(-1)

    print('Reading and verifying UPSs listed in {}. '.format(env.UtConst.UPS_JSON_FILE))
    ups = UPS.UPSsnmp()
    if not ups.set_daemon_parameters():
        ups.print_daemon_parameters()
        if env.UT_CONST.ups_config_ini:
            env.UT_CONST.log_print('Error reading [{}] file.'.format(env.UtConst.UPS_CONFIG_INI))
        else:
            env.UT_CONST.log_print('Error no [{}] file found.'.format(env.UtConst.UPS_CONFIG_INI))
        print('    For more information: `man {}`'.format(env.UtConst.UPS_CONFIG_INI))
        # env.UT_CONST.fatal = True

    num_ups = ups.get_num_ups_tuple()
    if num_ups[0] == 0:
        env.UT_CONST.log_print('No UPSs specified in {}'.format(env.UtConst.UPS_JSON_FILE))
        print('    For more information: `man {}`, exiting...'.format(env.UtConst.UPS_JSON_FILE))
        sys.exit(-1)
    print('{} UPSs listed in {} file.'.format(num_ups[0], env.UtConst.UPS_JSON_FILE))
    print('    {} are compatible, {} are accessible, {} are responsive'.format(num_ups[1], num_ups[2], num_ups[3]))
    if num_ups[0] != num_ups[3]:
        print('    Check the {} file.\n'.format(env.UtConst.UPS_JSON_FILE))

    if int(args.sleep) >= UPS.UPSsnmp.daemon_param_defaults['read_interval']['limit']:
        env.UT_CONST.SLEEP = int(args.sleep)
    else:
        env.UT_CONST.log_print('Invalid value for sleep specified.  Must be an integer >= {}'.format(
            UPS.UPSsnmp.daemon_param_defaults['read_interval']['limit']))
        env.UT_CONST.fatal = True

    if env.UT_CONST.fatal:
        env.UT_CONST.log_print('Fatal Error. Exiting...')
        sys.exit(-1)

    header_list = ['ups_type', 'ups_IP']
    if args.long:
        command_list = ups.get_monitor_mib_commands('all')
    else:
        command_list = ups.get_monitor_mib_commands()

    env.UT_CONST.show_unresponsive = args.show_unresponsive

    if args.log:
        env.UT_CONST.LOG = True
        env.UT_CONST.log_file = './log_monitor_{}.txt'.format(
            env.UT_CONST.now(ltz=env.UT_CONST.USELTZ).strftime('%m%d_%H%M%S'))
        env.UT_CONST.log_file_ptr = open(env.UT_CONST.log_file, 'w', 1)
        print_log_header(env.UT_CONST.log_file_ptr, header_list, command_list)

    if args.gui:
        # Display Gtk style Monitor
        devices = {}
        umonitor = MonitorWindow(ups, header_list, command_list, devices)
        umonitor.connect('delete-event', umonitor.set_quit)
        umonitor.show_all()

        # Start thread to update Monitor
        _monthread = threading.Thread(target=refresh, daemon=True, args=[env.UT_CONST.SLEEP,
                                      update_data, ups, header_list, command_list, devices, umonitor]).start()

        Gtk.main()
    else:
        # Display text style Monitor
        try:
            while True:
                ups_data = ups.read_all_ups_list_items(command_list, errups=args.show_unresponsive)
                if args.status:
                    print_monitor_table(ups, header_list, command_list, ups_data)
                    sys.exit(0)
                os.system('clear')
                if LOGGER.getEffectiveLevel() == logging.DEBUG:
                    print('%sDebug Logger Active%s' % ('\033[31m \033[01m', '\033[0m'))
                if env.UT_CONST.LOG:
                    print('%sLogging to:  %s%s' % ('\033[31m \033[01m', env.UT_CONST.log_file, '\033[0m'))
                    print_log(env.UT_CONST.log_file_ptr, header_list, command_list, ups_data)
                print_monitor_table(ups, header_list, command_list, ups_data)
                time.sleep(env.UT_CONST.SLEEP)
        except KeyboardInterrupt:
            if env.UT_CONST.LOG:
                env.UT_CONST.log_file_ptr.close()
            sys.exit(0)


if __name__ == '__main__':
    main()
