#!/usr/bin/env python3
"""tv_qt_class.py module called by tv_viewer
contains a class to handle the PyQt5 GUI of program"""
# =========================MODULE HEADER========================
# title             :tv_qt_class
# description       :Module from tv_viewer to handle the PyQt5 GUI of program
# author            :Gavin Lyons
# web               :https://github.com/gavinlyonsrepo/
# python_version    :3.10.4

# ==========================IMPORTS======================
# Import the system modules needed to run tv viewer.

import sys
import re
import glob
import subprocess
from pathlib import Path
import os

# External modules third party
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QPushButton, QMessageBox

# my modules
from tv_api_work import tv_api_work as myApi
from tv_sqllite import tv_sqllite as mySql
from tv_logger_conf import tv_logger_conf as myLog


# ================== GLOBALS ==========================

# setup logging
LOGGER = myLog.my_logging(__name__)
# define instance of the API class
my_tv_api = myApi.TvApi("myapiobject")
# define instance of the SQl class
my_tv_sql = mySql.TvSqLight("mysqlobject")

# ================== CLASSES SECTION ===============


class Ui_MainWindow():
    """This class display's the main window of the pyqt project"""
    def __init__(self):
        # ScreenStatus keeps track of what listinfo is displaying.
        self.screen_status_dict = {
            "mainScreen": 0, "selectShowScreen": 1,
            "favScreen": 2, "showDetailsScreen": 3}
        self.screen_status = self.screen_status_dict["mainScreen"]

    def setupUi(self, MainWindow):
        """ PYQT setup  UI generated by qtdesigner"""
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1100, 800)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        # Buttons
        self.search_btn = QtWidgets.QPushButton(self.centralwidget)
        self.search_btn.setGeometry(QtCore.QRect(20, 600, 120, 35))
        self.search_btn.setObjectName("search_btn")
        self.search_btn.setStyleSheet("border :3px solid;" "border-color : grey ")
        self.detail_btn = QtWidgets.QPushButton(self.centralwidget)
        self.detail_btn.setGeometry(QtCore.QRect(160, 600, 120, 35))
        self.detail_btn.setObjectName("detail_btn")
        self.detail_btn.setStyleSheet("border :3px solid;" "border-color : grey ")
        self.fav_btn = QtWidgets.QPushButton(self.centralwidget)
        self.fav_btn.setGeometry(QtCore.QRect(340, 600, 120, 35))
        self.fav_btn.setObjectName("fav_btn")
        self.fav_btn.setStyleSheet("border :3px solid;" "border-color : grey ")
        self.add_fav_btn = QtWidgets.QPushButton(self.centralwidget)
        self.add_fav_btn.setGeometry(QtCore.QRect(480, 600, 120, 35))
        self.add_fav_btn.setObjectName("add_fav_btn")
        self.add_fav_btn.setStyleSheet("border :3px solid;" "border-color : grey ")
        self.remove_fav_btn = QtWidgets.QPushButton(self.centralwidget)
        self.remove_fav_btn.setGeometry(QtCore.QRect(620, 600, 120, 35))
        self.remove_fav_btn.setObjectName("remove_fav_btn")
        self.remove_fav_btn.setStyleSheet("border :3px solid;" "border-color : grey ")
        self.reset_btn = QtWidgets.QPushButton(self.centralwidget)
        self.reset_btn.setGeometry(QtCore.QRect(760, 600, 120, 35))
        self.reset_btn.setObjectName("Reset")
        self.reset_btn.setStyleSheet("border :3px solid;" "border-color : grey ")
        self.exit_btn = QtWidgets.QPushButton(self.centralwidget)
        self.exit_btn.setGeometry(QtCore.QRect(895, 600, 70, 35))
        self.exit_btn.setObjectName("Exit")
        self.exit_btn.setStyleSheet("border :3px solid;" "border-color : grey ")
        self.busy_btn = QtWidgets.QPushButton(self.centralwidget)
        self.busy_btn.setGeometry(QtCore.QRect(895, 560, 65, 20))
        self.busy_btn.setObjectName("Busy")
        # radio buttons
        self.overview_rbtn = QtWidgets.QRadioButton(self.centralwidget)
        self.overview_rbtn.setGeometry(QtCore.QRect(970, 30, 136, 27))
        self.overview_rbtn.setObjectName("OverviewRbtn")
        self.overview_rbtn.setEnabled(False)
        self.actors_rbtn = QtWidgets.QRadioButton(self.centralwidget)
        self.actors_rbtn.setGeometry(QtCore.QRect(970, 80, 136, 27))
        self.actors_rbtn.setObjectName("ActorsRbtn")
        self.actors_rbtn.setEnabled(False)
        self.seasons_rbtn = QtWidgets.QRadioButton(self.centralwidget)
        self.seasons_rbtn.setGeometry(QtCore.QRect(970, 130, 136, 27))
        self.seasons_rbtn.setObjectName("seasonRbtn")
        self.seasons_rbtn.setEnabled(False)
        self.crews_rbtn = QtWidgets.QRadioButton(self.centralwidget)
        self.crews_rbtn.setGeometry(QtCore.QRect(970, 180, 136, 27))
        self.crews_rbtn.setObjectName("crewsRbtn")
        self.crews_rbtn.setEnabled(False)
        self.info_rbtn = QtWidgets.QRadioButton(self.centralwidget)
        self.info_rbtn.setGeometry(QtCore.QRect(970, 230, 136, 27))
        self.info_rbtn.setObjectName("infoRbtn")
        self.info_rbtn.setEnabled(False)
        self.episode_rbtn = QtWidgets.QRadioButton(self.centralwidget)
        self.episode_rbtn.setGeometry(QtCore.QRect(970, 280, 136, 27))
        self.episode_rbtn.setObjectName("episodeRbtn")
        self.episode_rbtn .setEnabled(False)
        # dial
        self.dial = QtWidgets.QDial(MainWindow)
        self.dial.setGeometry(QtCore.QRect(285, 610, 50, 64))
        self.dial.setObjectName("dial")
        self.dial.setMinimum(1)
        self.dial.setMaximum(6)
        self.dial.setValue(0)
        self.dial.valueChanged.connect(self.dial_changed)
        self.dial.setStyleSheet('background-color : grey')
        # List box
        self.listinfo = QtWidgets.QListWidget(self.centralwidget)
        self.listinfo.setGeometry(QtCore.QRect(20, 30, 940, 505))
        self.listinfo.setObjectName("listinfo")
        self.listinfo.setWordWrap(True)
        self.listinfo.setFrameShape(QtWidgets.QFrame.WinPanel)
        self.listinfo.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.listinfo.setProperty("isWrapping", False)
        self.listinfo.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
        self.listinfo.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerPixel)
        self.listinfo.setMovement(QtWidgets.QListView.Static)
        self.listinfo.itemSelectionChanged.connect(self.selection_changed)
        # text box
        self.text_enter = QtWidgets.QLineEdit(self.centralwidget)
        self.text_enter.setGeometry(QtCore.QRect(20, 560, 440, 32))
        self.text_enter.setObjectName("text_enter")
        # labels
        self.mainlbl = QtWidgets.QLabel(self.centralwidget)
        self.mainlbl.setGeometry(QtCore.QRect(20, 5, 301, 22))
        self.mainlbl.setFrameShape(QtWidgets.QFrame.Panel)
        self.mainlbl.setObjectName("mainlbl")
        self.txtlbl = QtWidgets.QLabel(self.centralwidget)
        self.txtlbl.setGeometry(QtCore.QRect(20, 535, 90, 22))
        self.txtlbl.setFrameShape(QtWidgets.QFrame.Panel)
        self.txtlbl.setObjectName("txtlbl")
        self.txtbusylbl = QtWidgets.QLabel(self.centralwidget)
        self.txtbusylbl.setGeometry(QtCore.QRect(895, 540, 65, 22))
        self.txtbusylbl.setFrameShape(QtWidgets.QFrame.Panel)
        self.txtbusylbl.setObjectName("txtbusylbl")
        MainWindow.setCentralWidget(self.centralwidget)
        # menubar
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 30))
        self.menubar.setObjectName("menubar")
        self.menu_file = QtWidgets.QMenu(self.menubar)
        self.menu_file.setObjectName("menuFile")
        MainWindow.setMenuBar(self.menubar)
        # add action to menus
        self.action_about = QtWidgets.QAction(MainWindow)
        self.action_about.setObjectName("action_about")
        self.action_log = QtWidgets.QAction(MainWindow)
        self.action_log.setObjectName("action_log")
        self.action_config = QtWidgets.QAction(MainWindow)
        self.action_config.setObjectName("action_config")
        self.action_exit = QtWidgets.QAction(MainWindow)
        self.action_exit.setObjectName("action_exit")
        self.menu_file.addAction(self.action_about)
        self.menu_file.addAction(self.action_log)
        self.menu_file.addAction(self.action_config)
        self.menu_file.addAction(self.action_exit)
        self.menubar.addAction(self.menu_file.menuAction())
        # status bar
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        self.statusbar.ensurePolished()
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        """ PYQT config for form :: created by Qt designer """
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Tv Viewer"))
        # Push Buttons
        self.search_btn.setText(_translate("MainWindow", "Search"))
        self.search_btn.clicked.connect(self.search_button_click)
        self.detail_btn.setText(_translate("MainWindow", "Details"))
        self.detail_btn.setEnabled(False)
        self.detail_btn.clicked.connect(self.details_button_click)
        self.fav_btn.setText(_translate("MainWindow", "Favorites"))
        self.fav_btn.setStatusTip('Display favorites Database')
        self.fav_btn.clicked.connect(self.fav_button_click)
        self.add_fav_btn.setText(_translate("MainWindow", "Add Favorite"))
        self.add_fav_btn.setStatusTip('Add chosen maze ID to favorites Database')
        self.add_fav_btn.clicked.connect(self.addfav_button_click)
        self.add_fav_btn.setEnabled(False)
        self.remove_fav_btn.setText(_translate("MainWindow", "Del Favorite"))
        self.remove_fav_btn.setStatusTip('Remove chosen maze ID from favorites Database')
        self.remove_fav_btn.clicked.connect(self.delfav_button_click)
        self.remove_fav_btn.setEnabled(False)
        self.reset_btn.setText(_translate("MainWindow", "Reset"))
        self.reset_btn.clicked.connect(self.reset_screen)
        self.exit_btn.setText(_translate("MainWindow", "Exit"))
        self.exit_btn.clicked.connect(self.close_application)
        self.busy_btn.setStyleSheet('background-color : green')
        # labels
        self.mainlbl.setText(_translate("MainWindow", "Information Display"))
        self.txtlbl.setText(_translate("MainWindow", "Input Box"))
        self.txtbusylbl.setText(_translate("MainWindow", "Status"))
        # Menubar events
        self.menu_file.setTitle(_translate("MainWindow", "Menu"))
        # about
        self.action_about.setText(_translate("MainWindow", "About"))
        self.action_about.setShortcut("Ctrl+A")
        self.action_about.setStatusTip('App info')
        self.action_about.triggered.connect(self.display_about)
        # view log file
        self.action_log.setText(_translate("MainWindow", "LogFile"))
        self.action_log.setShortcut("Ctrl+L")
        self.action_log.setStatusTip('Display the latest log file')
        self.action_log.triggered.connect(self.log_file_view)
        # view config file
        self.action_config.setText(_translate("MainWindow", "ConfigFile"))
        self.action_config.setShortcut("Ctrl+G")
        self.action_config.setStatusTip('Display the config file')
        self.action_config.triggered.connect(self.config_file_view)
        # exit menu item
        self.action_exit.setText(_translate("MainWindow", "&Exit"))
        self.action_exit.setShortcut("Ctrl+Q")
        self.action_exit.setStatusTip('Leave The App')
        self.action_exit.triggered.connect(self.close_application)
        # radio buttons
        self.overview_rbtn.setText(_translate("MainWindow", "Overview"))
        self.actors_rbtn.setText(_translate("MainWindow", "Actors"))
        self.seasons_rbtn.setText(_translate("MainWindow", "Seasons"))
        self.crews_rbtn.setText(_translate("MainWindow", "Crews"))
        self.info_rbtn.setText(_translate("MainWindow", "More Info"))
        self.episode_rbtn.setText(_translate("MainWindow", "Episodes"))

        self.start_screen()
        my_tv_sql.create_db()
        self.network_check()

    def close_application(self):
        """ Method control exit of program on exit button click closes database"""
        my_tv_sql.close_db()
        LOGGER.info(' Program Exiting ')
        sys.exit()

    def dial_changed(self):
        """ method to control what happens when dial is changed
        it control which radio button is set"""
        value = self.dial.value()
        if value == 1:
            self.overview_rbtn.setChecked(True)
        elif value == 2:
            self.actors_rbtn.setChecked(True)
        elif value == 3:
            self.seasons_rbtn.setChecked(True)
        elif value == 4:
            self.crews_rbtn.setChecked(True)
        elif value == 5:
            self.info_rbtn.setChecked(True)
        elif value == 6:
            self.episode_rbtn.setChecked(True)

    def busy_indicator(self, status):
        """ This method controls colour of busy/status bar"""
        if status == "ready":
            self.busy_btn.setStyleSheet('background-color : green')
        elif status == "busy":
            self.busy_btn.setStyleSheet('background-color : yellow')
            self.busy_btn.repaint()

    def network_check(self):
        """ Method to check if network is up ,
        can be turned off in config file
        uses sub process ping"""
        try:
            if myLog.myconfigfile.network_on_off == "on":
                result = subprocess.call(
                    ['ping', '-q', '-c', '1', myLog.myconfigfile.network_url])
                if result == 0:  # OK response
                    self.busy_btn.setStyleSheet('background-color : green')
                    LOGGER.info("network OK :: %s", myLog.myconfigfile.network_url)
                elif result == 2:  # no response
                    self.busy_btn.setStyleSheet('background-color : red')
                    LOGGER.exception(
                        " Problem with network no response :: %s",
                        myLog.myconfigfile.network_url)
                else:  # failed
                    LOGGER.exception(
                        " Problem with network failed ping :: %s",
                        myLog.myconfigfile.network_url)
                    self.busy_btn.setStyleSheet('background-color : red')
        except Exception as error:
            LOGGER.exception("Problem with network  %s ", error)
            self.busy_btn.setStyleSheet('background-color : red')

    def display_about(self):
        """ Method to display about information on menubar help click"""
        self.listinfo.clear()
        self.listinfo.addItem("\n GUI program to view tv program details using tvmaze API \
                               \n Version :: 2.0 \
                               \n Copyright :: Gavin Lyons 2017 GPL \
                               \n URL :: https://github.com/gavinlyonsrepo/tv_viewer ")

    def log_file_view(self):
        """ Displays the latest log file """
        self.listinfo.clear()
        try:
            # Get newest log file
            log_file_dir = Path(myLog.myconfigfile.log_file)
            file_type = r'TV*.log'
            newest_log_file = max(log_file_dir.glob(file_type), key=lambda f: f.stat().st_ctime)
            self.listinfo.addItem("Newest log file contents below :: " + str(newest_log_file))
            with open(newest_log_file, "r", encoding="utf-8") as file1:
                self.listinfo.addItem(file1.read())
        except ValueError:  # no files found
            self.listinfo.addItem(
                "No log files found at :: " + str(myLog.myconfigfile.log_file))
            LOGGER.exception(" No log files found ")
        except FileNotFoundError:
            self.statusbar.showMessage("Problem reading newest log file ::  "
                                       "FileNotFoundError", 2000)
            LOGGER.exception("Error reading log files FileNotFoundError")
        except Exception as error:
            self.statusbar.showMessage("Problem reading newest log file :: ", 2000)
            LOGGER.exception(" Error reading log files %s ", error)

    def config_file_view(self):
        """ displays the config file"""
        self.listinfo.clear()
        try:
            config_file_path = myLog.myconfigfile.config_file_path / "tvviewer.cfg"
            self.listinfo.addItem("Contents of config file at :: " + str(config_file_path))
            with open(config_file_path, "r", encoding="utf-8") as file1:
                self.listinfo.addItem(file1.read())
        except FileNotFoundError:
            self.statusbar.showMessage(
                "Problem reading config file ::  FileNotFoundError", 2000)
            LOGGER.exception("Error reading config files FileNotFoundError")

    def set_radio_buttons(self, on_off):
        """ enables or disables the radio buttons
        Param1 : True = on  , False = off """
        if on_off:
            self.seasons_rbtn.setEnabled(True)
            self.overview_rbtn.setEnabled(True)
            self.crews_rbtn.setEnabled(True)
            self.episode_rbtn.setEnabled(True)
            self.actors_rbtn.setEnabled(True)
            self.info_rbtn.setEnabled(True)
        else:
            self.seasons_rbtn.setEnabled(False)
            self.overview_rbtn.setEnabled(False)
            self.crews_rbtn.setEnabled(False)
            self.episode_rbtn.setEnabled(False)
            self.actors_rbtn.setEnabled(False)
            self.info_rbtn.setEnabled(False)

    def reset_screen(self):
        """ reset button clicked, resets screen to start status"""
        self.screen_status = self.screen_status_dict["mainScreen"]
        self.listinfo.clear()
        self.text_enter.clear()
        self.mainlbl.setText("Information Display")
        self.search_btn.setEnabled(True)
        self.detail_btn.setEnabled(False)
        self.fav_btn.setEnabled(True)
        self.add_fav_btn.setEnabled(False)
        self.remove_fav_btn.setEnabled(False)
        self.set_radio_buttons(False)
        self.busy_btn.setStyleSheet('background-color : green')
        self.network_check()
        self.start_screen()

    def start_screen(self):
        """initialise start screen list box"""
        self.listinfo.addItem("Welcome: ")
        self.listinfo.addItem("\nPress Search button to search for TV"
                              " Series based on text in Input box")
        self.listinfo.addItem("\nPress View Favs button for Favourites screen")
        self.listinfo.addItem("\nPress Reset button to reset screen")

    def search_button_zero(self):
        """ When show button is called from screen 0 (main) """
        msg = QMessageBox()
        if self.text_enter.text():
            self.network_check()
            self.busy_indicator("busy")
            items = my_tv_api.search_tv_series(self.text_enter.text())
            self.busy_indicator("ready")
            if not items:
                msg.setIcon(QMessageBox.Warning)
                msg.setWindowTitle("Message Box 1014")
                msg.setText("There Is No Matching Tv Show :- " + self.text_enter.text())
                msg.exec_()
                self.fav_btn.setEnabled(True)
            else:
                self.listinfo.clear()
                items = str(items)
                table_row = ""
                for character in str(items):
                    if character == '\n':
                        self.listinfo.addItem(table_row)
                        table_row = ""
                    else:
                        table_row = ''.join((table_row, character))

                self.text_enter.clear()
                self.screen_status = self.screen_status_dict["selectShowScreen"]
                self.mainlbl.setText("TV show selection screen")
                return
        else:
            msg.setIcon(QMessageBox.Warning)
            msg.setWindowTitle("Message Box 1012")
            msg.setText("Enter a TV show name in Input Box & press Enter")
            msg.exec_()
            self.fav_btn.setEnabled(True)

    def search_button_one(self, called_from):
        """ When search button is pressed
        called from screen 1 (select tv show) = 1
        called from screen 2 (view favs) when = 2
        Part 1 empty text box ?
        Part 2 valid data? and fetch data(items)
        Part 3 Is data(items) returned from API?
        Part 4 update screen
        Part 5 extract maze_id from data and place in input box if called from one
        """
        try:
            # check 1  no text in input box check
            if not self.text_enter.text():
                if called_from == 1:
                    self.statusbar.showMessage("Select a Row number and press Enter", 2000)
                elif called_from == 2:
                    self.statusbar.showMessage("Pick a Fav show and press Enter", 2000)
                return

            # check 2 valid data + Put show data in items
            # called from screen 1 = check valid row number
            # called from screen 2 = check if maze_id  is in favs database
            msg = QMessageBox()
            self.busy_indicator("busy")
            if called_from == 1:  # row number
                if not self.text_enter.text().isdecimal():
                    self.statusbar.showMessage(
                        "Not a Valid row Number :: "
                        + self.text_enter.text(), 2000)
                    self.busy_indicator("ready")
                    self.text_enter.clear()
                    return
                items = my_tv_api.show_tv_series(self.text_enter.text(), "No show name")
            elif called_from == 2:  # maze ID
                showflag = my_tv_sql.scan_db(self.text_enter.text())
                if not showflag:  # not in  the fav db
                    self.text_enter.clear()
                    self.statusbar.showMessage("Not a Valid maze ID", 2000)
                    self.busy_indicator("ready")
                    return
                show_name = my_tv_api.showname_get(self.text_enter.text())
                items = my_tv_api.show_tv_series(0, str(show_name))
                self.busy_indicator("ready")

            # Check 3 API returned something?
            if not items:  # no
                msg.setIcon(QMessageBox.Warning)
                msg.setWindowTitle("Message Box 1011")
                msg.setText("Invalid Data from API for this show:: " + str(items))
                msg.exec_()
            else:  # yes
                self.screen_status = self.screen_status_dict["showDetailsScreen"]
                self.listinfo.clear()
                self.listinfo.addItem(str(items))  # Display the data
                self.search_btn.setEnabled(False)
                self.detail_btn.setEnabled(True)
                self.remove_fav_btn.setEnabled(True)
                self.add_fav_btn.setEnabled(True)
                self.set_radio_buttons(True)
                self.mainlbl.setText("Tv show information screen")
                # Extract the maze ID from data items and place in text box
                if called_from == 1:
                    maze_id = ""
                    count_rows = 1
                    for character in str(items):
                        if character == '\n':
                            count_rows = count_rows + 1
                            if count_rows == 5:
                                # Remove excess white space
                                maze_id = re.sub(" +", " ", maze_id)
                                maze_id = maze_id.split(' ')[2]
                                self.text_enter.setText(maze_id)
                                break
                            maze_id = ""
                        else:
                            if count_rows == 4:
                                maze_id = ''.join((maze_id, character))
        except Exception as error:
            LOGGER.exception(
                "Failed to display tv show data and maze_id from api %s", error)
        finally:
            self.busy_indicator("ready")

    def search_button_click(self):
        """ Search  Button clicked method """
        self.fav_btn.setEnabled(False)
        if self.screen_status == 0:
            self.search_button_zero()
        elif self.screen_status == 1:
            self.search_button_one(1)
        elif self.screen_status == 2:
            self.search_button_one(2)

    def details_button_click(self):
        """ method to control button 2 details click"""
        self.busy_indicator("busy")
        self.text_enter.clear()
        self.listinfo.clear()
        self.remove_fav_btn.setEnabled(False)
        self.add_fav_btn.setEnabled(False)
        # Scan radio buttons to see if selected run the function for that selection
        # pass the row no of table to relevant TvApi function so it knows show
        if self.overview_rbtn.isChecked():
            self.listinfo.addItem(str(my_tv_api.overview(1)))
        elif self.actors_rbtn.isChecked():
            self.listinfo.addItem(str(my_tv_api.actors(0)))
        elif self.seasons_rbtn.isChecked():
            self.listinfo.addItem(str(my_tv_api.seasons(0)))
        elif self.crews_rbtn.isChecked():
            self.listinfo.addItem(str(my_tv_api.crews(0)))
        elif self.info_rbtn.isChecked():
            self.listinfo.addItem(str(my_tv_api.more_info(1)))
        elif self.episode_rbtn.isChecked():
            self.listinfo.addItem(str(my_tv_api.episode(0)))
        else:
            self.listinfo.addItem("Select an option from side bar:-")
        self.busy_indicator("ready")

    def fav_button_click(self):
        """ method to control button 3 FAVOURITES click """
        self.network_check()
        self.remove_fav_btn.setEnabled(True)
        self.add_fav_btn.setEnabled(True)
        self.fav_btn.setEnabled(False)
        self.search_btn.setEnabled(True)
        self.screen_status = self.screen_status_dict["mainScreen"]
        self.listinfo.clear()
        self.busy_indicator("busy")
        # load the fav's menu
        try:
            items = my_tv_api.favour_show(my_tv_sql.display_db())
            if items:
                table_row = ""
                for character in str(items):
                    if character == '\n':
                        self.listinfo.addItem(table_row)
                        table_row = ""
                    else:
                        table_row = ''.join((table_row, character))
            else:
                self.listinfo.addItem("No Favourites in database")
        except Exception as error:
            LOGGER.exception("Problem loading Favourites menu %s", error)
        else:
            self.mainlbl.setText("Favourites Information Screen")
            self.screen_status = self.screen_status_dict["favScreen"]
            self.statusbar.showMessage("Favourites Information Screen", 2000)
        finally:
            self.busy_indicator("ready")

    def addfav_button_click(self):
        """ method to control button 4 add FAVS click,
        adds a fav to database"""
        try:
            self.detail_btn.setEnabled(False)
            self.set_radio_buttons(False)
            mazeid = self.text_enter.text()
            msg = QMessageBox()
            if mazeid:  # text in the box?
                self.busy_indicator("busy")
                # check if in local fav database
                in_database = my_tv_sql.scan_db(mazeid)
                if in_database:
                    # Already in database, don't add
                    msg.setIcon(QMessageBox.Information)
                    msg.setWindowTitle("Message Box 1004")
                    msg.setText("That maze_id  already in the database:- " + mazeid)
                    msg.exec_()
                else:  # Not in database, check here if valid maze ID from API
                    show_name = my_tv_api.showname_get(mazeid)
                    if show_name != "Error":  # valid API -> add to database
                        my_tv_sql.add_db(mazeid, show_name)
                        self.fav_button_click()  # update
                        msg.setIcon(QMessageBox.Information)
                        msg.setText("Added maze_id to the database:- " + mazeid)
                        msg.setWindowTitle("Message Box 1005")
                        msg.exec_()
                    else:  # non-valid API
                        msg.setIcon(QMessageBox.Warning)
                        msg.setWindowTitle("Message Box 1006")
                        msg.setText("Cannot find that Maze_ID with API :- ")
                        msg.exec_()
                self.busy_indicator("ready")
            else:  # No text in the input box.
                msg.setIcon(QMessageBox.Warning)
                msg.setText("Add a Maze_Id to input box and press again :-")
                msg.setWindowTitle("Message Box 1007")
                msg.exec_()
        except Exception as error:
            LOGGER.exception(
                " Failure in delfav_button_click method :: %s", error)

    def delfav_button_click(self):
        """ method to control button 5 remove FAVS click
        deletes a fav from database"""
        try:
            self.detail_btn.setEnabled(False)
            self.set_radio_buttons(False)
            mazeid = self.text_enter.text()
            msg = QMessageBox()
            if mazeid:
                self.busy_indicator("busy")
                # check if in database
                in_database = my_tv_sql.scan_db(mazeid)
                if in_database:  # True, delete if in database
                    my_tv_sql.del_db(mazeid)
                    self.fav_button_click()  # update
                    msg.setIcon(QMessageBox.Information)
                    msg.setWindowTitle("Message Box 1000")
                    msg.setText("Removed maze_id from the database:-" + mazeid)
                    msg.exec_()
                else:  # not in database
                    msg.setIcon(QMessageBox.Information)
                    msg.setWindowTitle("Message Box 1002")
                    msg.setText("maze_id is not in the Favorite database:- " + mazeid)
                    msg.exec_()
                self.busy_indicator("ready")
            else:
                msg.setIcon(QMessageBox.Warning)
                msg.setText("Add a valid Maze_Id to input box and press again :- ")
                msg.setWindowTitle("Message Box 1003")
                msg.exec_()
        except Exception as error:
            LOGGER.exception(
                " Failure in delfav_button_click method :: %s", error)

    def selection_changed(self):
        """method to handle listinfo widget being changed by user"""
        try:
            if self.screen_status == self.screen_status_dict["favScreen"]:  # Fav screen
                if self.listinfo.currentRow() > 2:  # ignore top 3 lines of table titles
                    table_row = []
                    items = self.listinfo.selectedItems()
                    for i in range(len(items)):
                        table_row.append(str(self.listinfo.selectedItems()[i].text()))
                    table_row_string = str(table_row)
                    table_row_string = re.sub(" +", " ", table_row_string)  # Remove white space
                    table_row_string = table_row_string.split(' ')[4-1]
                    self.text_enter.setText(table_row_string)
                else:
                    self.text_enter.setText(" ")
            elif self.screen_status == 1:  # Screen tv show pick
                if self.listinfo.currentRow() > 2:  # ignore top 3 lines table titles
                    table_row = []
                    items = self.listinfo.selectedItems()
                    for i in range(len(items)):
                        table_row.append(str(self.listinfo.selectedItems()[i].text()))
                    table_row_string = str(table_row)
                    # Remove white space
                    table_row_string = re.sub(" +", " ", table_row_string)
                    table_row_string = table_row_string.split(' ')[2-1]
                    self.text_enter.setText(table_row_string)
                else:
                    self.text_enter.setText("0")
            else:
                pass
        except IndexError as error:
            self.text_enter.setText(" ")
            LOGGER.exception(
                " Failure in SelectionChanged Function :: %s", error)


# =====================MAIN====================
def test(text):
    """ Test module imported function """
    LOGGER.info(text)


if __name__ == '__main__':
    test("main")
else:
    test(" Imported " + __name__)
# =====================END==========
