from classes.User import User
from classes.Transaction import Tx
from helpers import TransactionHelper as transactionHelper
from helpers import BlockHelper as blockHelper
from helpers import TaskHelper as taskHelper
from helpers import UtilityHelper as utilityHelper

class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKCYAN = '\033[96m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

class MenuHelper:
    def __init__(self, db):
        self.db = db
        self.user = None

        self.start_menu = {}
        self.user_main_menu = {}
        self.user_blockchain_menu = {}
        self.user_settings_menu = {}

        self.start_menu[0] = "Exit"
        self.start_menu[1] = "Explore the Blockchain"
        self.start_menu[2] = "Login"
        self.start_menu[3] = "Sign up"

        self.user_main_menu[0] = "Exit"
        self.user_main_menu[1] = "User Settings"
        self.user_main_menu[2] = "Blockchain"
        self.user_main_menu[3] = "Log out"

        self.user_blockchain_menu[0] = "Back"
        self.user_blockchain_menu[1] = "Explore the Blockchain"
        self.user_blockchain_menu[2] = "View personal transactions"
        self.user_blockchain_menu[3] = "Pending transactions"
        self.user_blockchain_menu[4] = "Transfer coins"
        self.user_blockchain_menu[5] = "Check balance"
        self.user_blockchain_menu[6] = "Check the pool"
        self.user_blockchain_menu[7] = "Mine a block"

        self.user_settings_menu[0] = "Back"
        self.user_settings_menu[1] = "View account info"
        self.user_settings_menu[2] = "Change username"
        self.user_settings_menu[3] = "Change password"
        self.user_settings_menu[4] = "DELETE ACCOUNT"

        self.opened_logs = False

    def printMenu(self, items):
        for key, value in items.items():
            print(f'{key} -- {value}')

    def runStartMenu(self):
        while(True):

            choice = self.getMenuInput(self.start_menu)
            if choice == None:
                continue

            # check if choice is in menu
            match self.start_menu[choice]:
                case "Exit":
                    print('Exiting system')
                    exit()

                case "Explore the Blockchain":
                    blockHelper.exploreBlocks(self)

                case "Login":
                    self.user = User(self.db)
                    logged_in = self.user.login()
                    utilityHelper.clearScreen()
                    if logged_in:
                        print(f'Welcome {self.user.username}')
                        return
                    print("Login failed")
                    self.user = None

                case "Sign up":
                    self.user = User(self.db)
                    registered = self.user.register()
                    utilityHelper.clearScreen()
                    if registered:
                        print("Registration successful")
                        new_tx = Tx()
                        new_tx.createRewardTransaction(self.user.public_ser, self.user.private_ser, "SIGNUP")
                        if new_tx != False and new_tx.is_valid():
                            print("Received sign up bonus")
                            utilityHelper.saveFile("../data/transaction_pool.dat", new_tx)
                            return
                        print("Transaction is invalid")
                    print("Registration failed")
                    self.user = None
                                          
                case _:
                    print("Wrong input, try again")

    def runUserMainMenu(self):
        utilityHelper.loginStartup(self)
        while(self.user):

            choice = self.getMenuInput(self.user_main_menu)
            if choice == None:
                continue

            # check if choice is in menu
            match self.user_main_menu[choice]:
                case "Exit":
                    print('Exiting system')
                    exit()

                case "Log out":
                    self.user.logout()
                    self.user = None

                case "User Settings":
                    self.runUserSettingsMenu()

                case "Blockchain":
                    self.runUserBlockchainMenu()

                case _:
                    print("Wrong input, try again")

    def runUserBlockchainMenu(self):
        while(self.user):

            choice = self.getMenuInput(self.user_blockchain_menu)
            if choice == None:
                continue

            # check if choice is in menu
            match self.user_blockchain_menu[choice]:
                case "Back":
                    return

                case "Explore the Blockchain":
                    blockHelper.exploreBlocks(self)

                case "Pending transactions":
                    transactionHelper.pendingTransactions(self)

                case "View personal transactions":
                    taskHelper.getPersonalTransactions(self)

                case "Transfer coins":
                    new_tx = transactionHelper.transaction(self)
                    if new_tx != False and new_tx.is_valid():
                        print("Transaction is valid")
                        utilityHelper.saveFile("../data/transaction_pool.dat", new_tx)
                        continue
                    print("Transaction is invalid")


                case "Check balance":
                    balance = taskHelper.getBalance(self)
                    print(f"Your balance is: {balance}")
                    print(f"Your balance after verification of outgoing transactions: {taskHelper.getBalanceWithOutgoingPool(self, balance)}")

                case "Check the pool":
                    transactions = utilityHelper.loadFile("../data/transaction_pool.dat")
                    if len(transactions) == 0:
                        print("Transaction pool is empty")
                        continue
                    x = 0
                    for transaction in transactions:
                        x += 1
                        print(f"---------------------------------------{x}-------------------------------------------")
                        print(f"{transaction}")
                    print("---------------------------------------END-------------------------------------------")

                case "Mine a block":
                    blockHelper.createBlock(self)

                case _:
                    print("Wrong input, try again")

    def runUserSettingsMenu(self):
        while(self.user):

            choice = self.getMenuInput(self.user_settings_menu)
            if choice == None:
                continue

            # check if choice is in menu
            match self.user_settings_menu[choice]:
                case "Back":
                    return
                
                case "View account info":
                    self.user.printAccountInfo()
                
                case "Change username":
                    self.user.updateAccount()

                case "Change password":
                    self.user.updatePassword()

                case "DELETE ACCOUNT":
                    if self.user.deleteAccount():
                        self.user = None

                case _:
                    print("Wrong input, try again")

    def getMenuInput(self, menu):
        self.printMenu(menu)
        # make input an interger
        try:
            choice = int(input(">>: "))
        except:
            utilityHelper.clearScreen()
            print("Wrong input, try again")
            return None
        
        if choice >= len(menu):
            utilityHelper.clearScreen()
            print("Wrong input, try again")
            return None
        utilityHelper.clearScreen()

        return choice