#!/usr/bin/env python3
from tkinter import *
from tkinter import ttk

from player import Player
from table import Table

PLAYERS: list[Player] = []
TABLES: list[Table] = []
TABLES_HISTORY: list[Table] = []

TOTAL_SCORE = 4 * 30000

# init tkinter
root = Tk()
root.title("🀄 RonRunner - Mahjong Tournament Scoring 🀄")
root.geometry("800x500")

# configure style
style = ttk.Style()
style.theme_use('clam')

# configure scrollbar
canvas = Canvas(root, highlightthickness=0)
scrollbar = ttk.Scrollbar(root, orient='vertical', command=canvas.yview)
scrollbarFrame = ttk.Frame(canvas)
scrollbarFrame.bind(
    "<Configure>",
    lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
)

canvas.create_window((0, 0), window=scrollbarFrame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)

canvas.grid(column=0, row=0, sticky="nsew")
scrollbar.grid(column=1, row=0, sticky="ns")

root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)

frm = scrollbarFrame

# activate scrollbar with pad/mouse
def _on_mousewheel(event):
    canvas.yview_scroll(int(-1*(event.delta/120)), "units")

def _on_scroll_up(event):
    canvas.yview_scroll(-1, "units")

def _on_scroll_down(event):
    canvas.yview_scroll(1, "units")

def _bind_mousewheel(widget):
    widget.bind("<MouseWheel>", _on_mousewheel)
    widget.bind("<Button-4>", _on_scroll_up)
    widget.bind("<Button-5>", _on_scroll_down)
    for child in widget.winfo_children():
        _bind_mousewheel(child)

_bind_mousewheel(frm)

# init ui

# players
ttk.Label(frm, text="Rank", font=("Helvetica", 11, "bold")).grid(column=0, row=0, padx=10, pady=10)
ttk.Label(frm, text="Player", font=("Helvetica", 11, "bold")).grid(column=1, row=0, padx=10, pady=10)
ttk.Label(frm, text="Score", font=("Helvetica", 11, "bold")).grid(column=2, row=0, padx=10, pady=10)

entry_player_name = ttk.Entry(frm, width=30, font=("Helvetica", 10))
entry_player_name.grid(column=1, row=len(PLAYERS) + 1, padx=10, pady=10)

# adding player
def addPlayer(entry: Entry):
    txt = entry.get()
    if txt and not txt in [p.name for p in PLAYERS]:
        PLAYERS.append(Player(txt))
        entry.delete(0, END)
        refreshUi()

btn_player_name = ttk.Button(frm, text="➕ Add", command=lambda : addPlayer(entry_player_name))
btn_player_name.grid(column=2, row=len(PLAYERS) + 1, padx=10, pady=10)

# tables

# show tables


# create table
def addTable():
    popup = Toplevel(root)
    popup.title("Create a new table")
    popup.geometry("300x250")

    p1_var = StringVar(value="Select player 1")
    p2_var = StringVar(value="Select player 2")
    p3_var = StringVar(value="Select player 3")
    p4_var = StringVar(value="Select player 4")

    # names list
    names = [p.name for p in PLAYERS]

    ttk.Label(popup, text="Player 1", font=("Helvetica", 10)).grid(column=0, row=0, padx=10, pady=10)
    combo1 = ttk.Combobox(popup, textvariable=p1_var, values=names, state="readonly", width=25)
    combo1.grid(column=1, row=0, padx=10, pady=5)

    ttk.Label(popup, text="Player 2", font=("Helvetica", 10)).grid(column=0, row=1, padx=10, pady=10)
    combo2 = ttk.Combobox(popup, textvariable=p2_var, values=names, state="readonly", width=25)
    combo2.grid(column=1, row=1, padx=10, pady=5)

    ttk.Label(popup, text="Player 3", font=("Helvetica", 10)).grid(column=0, row=2, padx=10, pady=10)
    combo3 = ttk.Combobox(popup, textvariable=p3_var, values=names, state="readonly", width=25)
    combo3.grid(column=1, row=2, padx=10, pady=5)

    ttk.Label(popup, text="Player 4", font=("Helvetica", 10)).grid(column=0, row=3, padx=10, pady=10)
    combo4 = ttk.Combobox(popup, textvariable=p4_var, values=names, state="readonly", width=25)
    combo4.grid(column=1, row=3, padx=10, pady=5)

    def createTable():
        p1_name = p1_var.get()
        p2_name = p2_var.get()
        p3_name = p3_var.get()
        p4_name = p4_var.get()

        if p1_name != "Select player 1" and p2_name != "Select player 2" and p3_name != "Select player 3" and p4_name != "Select player 4":
            p1 = next((p for p in PLAYERS if p.name == p1_name), None)
            p2 = next((p for p in PLAYERS if p.name == p2_name), None)
            p3 = next((p for p in PLAYERS if p.name == p3_name), None)
            p4 = next((p for p in PLAYERS if p.name == p4_name), None)

            if len(set([p1, p2, p3, p4])) == 4:
                TABLES.append(Table(p1, p2, p3, p4))
                cancelTopLevel(popup)
    
    ttk.Button(popup, text="✓ Create", command=createTable).grid(column=1, row=4, padx=10, pady=20)
    ttk.Button(popup, text="✕ Cancel", command=lambda : cancelTopLevel(popup)).grid(column=2, row=4, padx=10, pady=20)

btn_create_table = ttk.Button(frm, text="➕ Create table", command=addTable)
btn_create_table.grid(column=1, row=len(PLAYERS) + 2, padx=10, pady=20)

# table history
# TODO

# refresh ui
def refreshUi():
    # remove old labels
    for widget in frm.winfo_children():
        if widget not in [
            entry_player_name,
            btn_player_name,
            btn_create_table
        ]:
            info = widget.grid_info()
            if info.get('row', 0) > 0 and info.get('row', 0) < 100:
                widget.destroy()

    # show players
    PLAYERS.sort(key=lambda p : p.score, reverse=True)
    for i in range(len(PLAYERS)):
        ttk.Label(frm, text=f"{i+1}", font=("Helvetica", 10, "bold"), foreground="#FF6B6B").grid(column=0, row=i+1, padx=10, pady=8)
        playerLabel = ttk.Label(frm, text=PLAYERS[i].name, font=("Helvetica", 10), foreground="#0066CC")
        playerLabel.grid(column=1, row=i+1, padx=10, pady=8)
        ttk.Label(frm, text=f"{PLAYERS[i].score}", font=("Helvetica", 10, "bold"), foreground="#2ECC71").grid(column=2, row=i+1, padx=10, pady=8)

        # change player name
        def onClick(event, player=PLAYERS[i]):
            popup = Toplevel(root)
            popup.title(f"Edit - {player.name}")
            popup.geometry("300x150")
            
            entry = ttk.Entry(popup, width=30, font=("Helvetica", 10))
            entry.insert(0, player.name)
            entry.grid(column=0, row=0, padx=10, pady=10)

            def changeName():
                name = entry.get()
                if name and not name in [p.name for p in PLAYERS]:
                    player.name = name
                    entry.delete(0, END)
                    cancelTopLevel(popup)

            ttk.Button(popup, text="✓ Change", command=changeName).grid(column=1, row=0, padx=5, pady=10)
            ttk.Button(popup, text="✕ Cancel", command=lambda : cancelTopLevel(popup)).grid(column=2, row=0, padx=5, pady=10)

        playerLabel.bind("<Button-1>", onClick)

    # adding player
    entry_player_name.grid(column=1, row=len(PLAYERS) + 1)
    btn_player_name.grid(column=2, row=len(PLAYERS) + 1)

    # show tables
    ttk.Label(frm, text="Tables", font=("Helvetica", 12, "bold")).grid(column=0, row=len(PLAYERS) + 3, columnspan=3, padx=10, pady=20)

    for i, table in enumerate(TABLES):
        nbCol = 4
        col = i % nbCol
        row = len(PLAYERS) + 4 + (i // nbCol)

        style = ttk.Style()
        style.theme_use('clam')

        if (table.s1 + table.s2 + table.s3 + table.s4 != TOTAL_SCORE):
            colour = "#F13C3C"
        else:
            colour = "#3CEB2C"
        style.configure("Table.TLabelframe", borderwidth=2, relief="solid", bordercolor=colour)

        tableFrame = ttk.LabelFrame(frm, text=f"Table {i+1}", padding=10, style="Table.TLabelframe")
        tableFrame.grid(column=col, row=row, padx=10, pady=10, sticky="ew")

        ttk.Label(tableFrame, text=table.p1.name, font=("Helvetica", 9)).pack()
        ttk.Label(tableFrame, text=table.p2.name, font=("Helvetica", 9)).pack()
        ttk.Label(tableFrame, text=table.p3.name, font=("Helvetica", 9)).pack()
        ttk.Label(tableFrame, text=table.p4.name, font=("Helvetica", 9)).pack()

        def onClick(event, table=table):
            popup = Toplevel(root)
            popup.title(f"Edit table")
            popup.geometry("300x250")

            p1_var = StringVar(value=table.p1.name)
            p2_var = StringVar(value=table.p2.name)
            p3_var = StringVar(value=table.p3.name)
            p4_var = StringVar(value=table.p4.name)

            # names list
            names = [p.name for p in PLAYERS]

            ttk.Label(popup, text="Player 1", font=("Helvetica", 10)).grid(column=0, row=0, padx=10, pady=10)
            combo1 = ttk.Combobox(popup, textvariable=p1_var, values=names, state="readonly", width=25)
            combo1.grid(column=1, row=0, padx=10, pady=5)
            entry1 = ttk.Entry(popup, width=30, font=("Helvetica", 10))
            entry1.insert(0, table.s1)
            entry1.grid(column=2, row=0, padx=10, pady=10)

            ttk.Label(popup, text="Player 2", font=("Helvetica", 10)).grid(column=0, row=1, padx=10, pady=10)
            combo2 = ttk.Combobox(popup, textvariable=p2_var, values=names, state="readonly", width=25)
            combo2.grid(column=1, row=1, padx=10, pady=5)
            entry2 = ttk.Entry(popup, width=30, font=("Helvetica", 10))
            entry2.insert(0, table.s2)
            entry2.grid(column=2, row=1, padx=10, pady=10)

            ttk.Label(popup, text="Player 3", font=("Helvetica", 10)).grid(column=0, row=2, padx=10, pady=10)
            combo3 = ttk.Combobox(popup, textvariable=p3_var, values=names, state="readonly", width=25)
            combo3.grid(column=1, row=2, padx=10, pady=5)
            entry3 = ttk.Entry(popup, width=30, font=("Helvetica", 10))
            entry3.insert(0, table.s3)
            entry3.grid(column=2, row=2, padx=10, pady=10)

            ttk.Label(popup, text="Player 4", font=("Helvetica", 10)).grid(column=0, row=3, padx=10, pady=10)
            combo4 = ttk.Combobox(popup, textvariable=p4_var, values=names, state="readonly", width=25)
            combo4.grid(column=1, row=3, padx=10, pady=5)
            entry4 = ttk.Entry(popup, width=30, font=("Helvetica", 10))
            entry4.insert(0, table.s4)
            entry4.grid(column=2, row=3, padx=10, pady=10)

            def changeTable():
                p1_name = p1_var.get()
                p2_name = p2_var.get()
                p3_name = p3_var.get()
                p4_name = p4_var.get()

                try:
                    s1 = int(entry1.get())
                    s2 = int(entry2.get())
                    s3 = int(entry3.get())
                    s4 = int(entry4.get())
                except:
                    return

                if p1_name != "Select player 1" and p2_name != "Select player 2" and p3_name != "Select player 3" and p4_name != "Select player 4":
                    p1 = next((p for p in PLAYERS if p.name == p1_name), None)
                    p2 = next((p for p in PLAYERS if p.name == p2_name), None)
                    p3 = next((p for p in PLAYERS if p.name == p3_name), None)
                    p4 = next((p for p in PLAYERS if p.name == p4_name), None)

                    if len(set([p1, p2, p3, p4])) == 4:
                        table.p1 = p1
                        table.p2 = p2
                        table.p3 = p3
                        table.p4 = p4

                        table.s1 = s1
                        table.s2 = s2
                        table.s3 = s3
                        table.s4 = s4
                        cancelTopLevel(popup)
            
            ttk.Button(popup, text="✓ Ok", command=changeTable).grid(column=1, row=4, padx=10, pady=20)
            ttk.Button(popup, text="✕ Cancel", command=lambda : cancelTopLevel(popup)).grid(column=2, row=4, padx=10, pady=20)

        tableFrame.bind("<Button-1>", onClick)
        for child in tableFrame.winfo_children():
            child.bind("<Button-1>", onClick)

    # adding table
    btn_create_table.grid(column=1, row=len(PLAYERS) + 2, padx=10, pady=20)

def cancelTopLevel(tl: Toplevel):
    tl.destroy()
    refreshUi()

refreshUi()
root.mainloop()