import random
from typing import List
import sys
if sys.platform == "win32":
    from colorama import just_fix_windows_console
    just_fix_windows_console()
from colorama import Fore, Back, Style
from termcolor import colored, cprint
# GLOBAL variables all caps becasue they are static and do not change.
MAX_LINES = 3
MAX_BET = 100
MIN_BET = 1
ROWS = 3
COLS = 3
# The list of sybmbols used in the slot machine. 
SYMBOL_COUNT = {
    "A": 2,
    "B": 4,
    "C": 6,
    "D": 8,
    "\u06de": 1,
    "\u16b0": 2,
    "\u16ca": 2,
    "\u16d4": 2,
    "\u16f8": 2
}
# The value when calculating bets of sybmbols used in the slot machine.
SYMBOL_VALUE = {
    "A": 5,
    "B": 4,
    "C": 3,
    "D": 2,
    "\u06de": 5,
    "\u16b0": 5,
    "\u16ca": 5,
    "\u16d4": 5,
    "\u16f8": 5
}
# The list of sybmbol colors used used in the slot machine.
SYMBOL_COLORS = {
    "A": Fore.CYAN,
    "B": Fore.GREEN,
    "C": Fore.LIGHTBLUE_EX,
    "D": Fore.RED,
    "\u06de": Fore.MAGENTA,
    "\u16b0": Fore.YELLOW,
    "\u16ca": Fore.WHITE,
    "\u16d4": Fore.BLUE,
    "\u16f8": Fore.LIGHTCYAN_EX
}
# This function does the calculations for the bet to see if the user won or lost.
def check_winings(columns: List, my_bet: int, my_lines: int):
    winnings = 0
    winning_lines = []
    for line in range(my_lines):
        symbol = columns[0][line]
        for column in columns:
            symbol_to_check = column[line]
            if symbol != symbol_to_check:
                break
        else:
            winnings += SYMBOL_VALUE[symbol] * my_bet
            winning_lines.append(line + 1)

    return winnings, winning_lines

    
# This function is for getting the symbols randomly
def get_slot_machine_spin() -> List:
    all_symbols = []
    # this is so as it picks from the list it gets the values and the index
    for symbol, count  in SYMBOL_COUNT.items():
        for _ in range(count):
            all_symbols.append(symbol)
    columns = []
    for col in range(COLS):
        column = []
        current_symbols = all_symbols[:]
        for row in range(ROWS):
            value = random.choice(current_symbols)
            current_symbols.remove(value)
            column.append(value)
        columns.append(column)
    return columns
# This function shows the rows and cloumns in a display like a real machine.
def print_slotmachine(columns: List):
    for row in range(ROWS):
        for index, column in enumerate(columns):
            if index != COLS - 1:
                print(SYMBOL_COLORS[column[row]] + column[row] + Fore.RESET, "| ", end='')
        else:
            print(SYMBOL_COLORS[column[row]] + column[row] + Fore.RESET)
#THis function takes the deposit or inoput of dollar amount from user. 
def deposit() -> int:
    """
    The function that has the user deposite the money they are going to be betting on

    It is stored as a variable int called amount.
    """
    amount = 0 
    while amount == 0:
        response = input("What would you like to depsoit? $")
        if response.isdigit():
            amount = int(response)
            if amount == 0:
                print(Fore.RED + "   Error: Amount must be greater than zero" + Fore.RESET)
        else: 
            print(Fore.RED + "   Error: Please enter a number" + Fore.RESET)
    return amount
# This function asks the user how many rows are they betting on 1 to 3
def get_number_of_lines() -> int:
    """
    This function asks for how many rows they want to bet on.

    """
    lines = 0
    while lines < 1 or lines > MAX_LINES:
            response = input("Enter the number of lines to bet on (1-" + str(MAX_LINES) + ")? ")
            if response.isdigit():
                lines = int(response)
                if lines < 1 or lines > MAX_LINES:
                    print("   Error: Enter a valid number of lines.")
            else: 
                print("   Error: Please enter a number")
    return lines

# This function asks the user how much they want to bet on each line. 
def get_bet() -> int:
    """
    THis function asks the user how much they want to bet per row.
    """
    bet = 0
    while bet < MIN_BET or  bet > MAX_BET:
        amount = input("What would you like to Bet on each line? $")
        if amount.isdigit():
            bet = int(amount)
            if bet < MIN_BET or bet > MAX_BET:
                print(f"  Error: Amount must be between ${MIN_BET} - ${MAX_BET}.")
        else: 
            print("  Error: Please enter a number")
    return bet

# This takes the bet rows and random sybmols from other functions and spits out if
# they win or lose and how much. 
def roll(balance) -> int:
    lines = get_number_of_lines()
    bet = -1
    total_bet = balance + 1
    while bet != 0 and total_bet > balance:
        bet = get_bet()
        total_bet = bet * lines
        if total_bet > balance:
            print(f"  Error: You do not have enough to bet that amount, curent balance is: ${balance} ")
    if total_bet == 0:
        return
    print(f"You are betting ${bet} on {lines} lines. Total bet is equal to: ${total_bet} ")

    slots = get_slot_machine_spin()
    print_slotmachine(slots)
    winnings, winning_lines = check_winings(slots, bet, lines)
    print(f"You won ${winnings}.")
    if len(winning_lines) > 0:
        print(f"You won on line" + ("s" if len(winning_lines) > 1 else "") + ":", *winning_lines)
        balance = balance + winnings
    else:
        print(f"You lost your bet of ${bet} on {lines} lines for a total loss of ${bet*lines}")
        balance = balance - (bet * lines)
    return balance

# This loop is the playing fucntion that takes the bet and seees if they have anymore mony to bet with or if they want to keep going.
def main():
    balance = deposit()
    # Using "while True" requires a break to exit.
    # Should instead be a conditional that tracks the actual exit conditions
    playing = True
    while playing is True:
        balance = roll(balance)
        print(f"Current Balance is ${balance}")
        if balance > 0:
            answer = input("Press enter to play (q to quit).")
            if answer.lower() == "q":
                playing = False
        else:
            playing = False
    print(f"You left with ${balance}")

main()
print()
print("Thank you for playing!")