import tkinter as tk
import sys
from tkinter import ttk, messagebox
import random
import numpy as np
from scipy.spatial.distance import cityblock

# Configurações do tabuleiro (tamanho (X,Y), orçamento inicial, Custo dos sensores)
if len(sys.argv) > 1:
    ROWS = int(sys.argv[1])
    COLS = int(sys.argv[2])
else:
    ROWS,COLS = 5,5


class TreasureGame:
    def __init__(self, root):
        self.root = root
        self.root.title("Caçadores da Arca Perdida")

        # Inicialização de variáveis de estado
        self.perfect_mode = False
        self.INITIAL_BUDGET = 100
        self.SENSOR_COSTS = {"GPR": 5, "MAG": 3, "VIS": 1, "DIG": 0}

        self.budget = self.INITIAL_BUDGET
        self.ark_loc = (random.randint(0, ROWS - 1), random.randint(0, COLS - 1))
        #self.ark_loc = (1,1)
        self.probs = np.full((ROWS, COLS), 1.0 / (ROWS * COLS))
        self.used_sensors = set()
        self.cell_history = {}
        self.show_treasure_debug = False
        # Tabelas de Probabilidade Normais
        self.SENSOR_TABLES = {
            "GPR": {
                "STRONG": [0.75, 0.10, 0.05, 0.02],
                "MODERATE": [0.15, 0.70, 0.15, 0.08],
                "WEAK": [0.07, 0.15, 0.65, 0.15],
                "NONE": [0.03, 0.05, 0.15, 0.75]
            },
            "MAG": {
                "HIGH": [0.70, 0.15, 0.10],
                "MEDIUM": [0.20, 0.65, 0.25],
                "LOW": [0.10, 0.20, 0.65]
            },
            "VIS": {
                "SUSPICIOUS": [0.60, 0.20],
                "NORMAL": [0.40, 0.80]
            }
        }
        # Tabelas de Probabilidade Perfeitas
        self.SENSOR_TABLES_PERFECT = {
            "GPR": {
                "STRONG": [1, 0, 0, 0],
                "MODERATE": [0, 1, 0, 0],
                "WEAK": [0, 0, 1, 0],
                "NONE": [0, 0, 0, 1],
            },
            "MAG": {
                "HIGH": [1, 0, 0],
                "MEDIUM": [0, 1, 0],
                "LOW": [0, 0, 1]
            },
            "VIS": {
                "SUSPICIOUS": [1, 0],
                "NORMAL": [0, 1]
            }
        }


        # Estilos dos botões
        self.style = ttk.Style()
        self.style.configure("Perfect.TButton", foreground="green", font=("Arial", 9, "bold"))
        self.style.configure("Normal.TButton", foreground="black")

        self.setup_ui()

    # Define os sensores utilizados
    @property
    def current_sensor_table(self):
        return self.SENSOR_TABLES_PERFECT if self.perfect_mode else self.SENSOR_TABLES

    def setup_ui(self):
        # Tabuleiro INICIO
        self.main_frame = ttk.Frame(self.root, padding="10")
        self.main_frame.grid(row=0, column=0, sticky="nsew")

        self.buttons = {}
        for r in range(ROWS):
            for c in range(COLS):
                btn = tk.Button(self.main_frame, text="", width=15, height=5,
                                font=("Arial", 8), relief="groove",
                                command=lambda row=r, col=c: self.cell_click(row, col))
                btn.grid(row=r, column=c, padx=2, pady=2, sticky="nsew")
                self.buttons[(r, c)] = btn
        # Tabuleiro FIM
        # Menu Lateral INICIO
        control_panel = ttk.Frame(self.root, padding="10")
        control_panel.grid(row=0, column=1, sticky="ns")

        # Texto Orçamento
        self.budget_var = tk.StringVar(value=f"Orçamento: {self.budget}")
        ttk.Label(control_panel, textvariable=self.budget_var, font=("Arial", 12, "bold")).pack(pady=5)

        # RadioButton Sensores
        self.sensor_var = tk.StringVar(value="GPR")
        sf = ttk.LabelFrame(control_panel, text=" Selecione o Sensor ", padding="5")
        sf.pack(fill='x', pady=5)
        for s, cost in self.SENSOR_COSTS.items():
            ttk.Radiobutton(sf, text=f"{s} ({cost})", variable=self.sensor_var, value=s).pack(anchor='w')

        # Botão Revelar tesouro
        self.reveal_btn = ttk.Button(control_panel, text="Revelar Tesouro: OFF", command=self.toggle_treasure,
                                     style="Normal.TButton")
        self.reveal_btn.pack(fill='x', pady=10)

        # Botão Sensores Perfeitos
        self.perfect_btn = ttk.Button(control_panel, text="Sensores Perfeitos: OFF", command=self.toggle_perfect_mode,
                                      style="Normal.TButton")
        self.perfect_btn.pack(fill='x', pady=5)

        # Painel Histórico
        ttk.Label(control_panel, text="Histórico:").pack(anchor='w', pady=(10, 0))
        self.history_log = tk.Text(control_panel, width=30, height=12, state='disabled', font=("Consolas", 9))
        self.history_log.pack(pady=5)

        # Botão Reiniciar
        ttk.Button(control_panel, text="Reiniciar Jogo", command=self.reset_game).pack(fill='x', pady=2)

        # Botão Sair
        ttk.Button(control_panel, text="Sair", command=self.root.destroy).pack(fill='x', pady=5)

        # Menu lateral FIM
        self.update_grid_display()

    # Activa/Desactiva sensores perfeitos
    def toggle_perfect_mode(self):
        self.perfect_mode = not self.perfect_mode
        if self.perfect_mode:
            self.perfect_btn.config(text="Sensores Perfeitos: ON", style="Perfect.TButton")
        else:
            self.perfect_btn.config(text="Sensores Perfeitos: OFF", style="Normal.TButton")

        self.history_log.config(state='normal')
        self.history_log.insert(tk.END, f"> Modo Sensores Perfeitos: {'ON' if self.perfect_mode else 'OFF'}\n")
        self.history_log.see(tk.END)
        self.history_log.config(state='disabled')

    # Activa/Desactiva localização do tesouro
    def toggle_treasure(self):

        self.show_treasure_debug = not self.show_treasure_debug
        if self.show_treasure_debug:
            self.reveal_btn.config(text="Revelar Tesouro: ON", style="Perfect.TButton")
        else:
            self.reveal_btn.config(text="Revelar Tesouro: OFF", style="Normal.TButton")

        self.history_log.config(state='normal')
        self.history_log.insert(tk.END, f"> Modo Tesouro Visivel: {'ON' if self.show_treasure_debug else 'OFF'}\n")
        self.history_log.see(tk.END)
        self.history_log.config(state='disabled')

        self.update_grid_display()

    # Actualiza o tabuleiro
    def update_grid_display(self):
        for (r, c), btn in self.buttons.items():
            treasure_header = "!!! TESOURO !!!\n" if (self.show_treasure_debug and (r, c) == self.ark_loc) else ""
            p_text = f"{self.probs[r, c]:.1%}"
            history_text = self.cell_history.get((r, c), "")
            if history_text:
                history_text = "\n" + history_text

            btn.config(text=f"{treasure_header}{p_text}{history_text}")

            # Cor de fundo baseada na probabilidade
            intensity = int(255 - (self.probs[r, c] * 350))
            intensity = max(min(intensity, 255), 180)
            color = f"#{255:02x}{intensity:02x}{intensity:02x}"

            if self.show_treasure_debug and (r, c) == self.ark_loc:
                color = "#FFD700"  # Dourado

            btn.config(bg=color)

    # Click das localizações do mapa
    def cell_click(self, r, c):
        sensor = self.sensor_var.get()
        cost = self.SENSOR_COSTS[sensor]

        # Verifica o se sensor já foi usado na localização
        if sensor != "DIG" and (r, c, sensor) in self.used_sensors:
            messagebox.showwarning("Aviso", "Este sensor já foi usado aqui!")
            return

        # Verifica se há orçamento
        if self.budget < cost:
            messagebox.showwarning("Aviso", "Orçamento insuficiente!")
            return

        # Se o jogador utilizou "DIG" verifica se ganhou ou perdeu
        if sensor == "DIG":
            if (r, c) == self.ark_loc:
                messagebox.showinfo("Vitória", f"Encontrou o tesouro!\nPontuação final: {self.budget}")
            else:
                messagebox.showerror("Derrota", f"O tesouro não está nesta localização.\nPerdeu o jogo!")
            self.root.destroy()
            return

        # Executa o sensor, com base na tabela utilizada
        dist = cityblock((r, c), self.ark_loc)
        active_table = self.current_sensor_table[sensor]

        # Determinar leitura baseada nas probabilidades
        outcomes = list(active_table.keys())
        max_idx = len(next(iter(active_table.values()))) - 1
        idx = min(dist, max_idx)
        weights = [active_table[out][idx] for out in outcomes]
        print(weights)
        reading = random.choices(outcomes, weights=weights, k=1)[0]


        # Actualiza orçamento
        self.used_sensors.add((r, c, sensor))
        self.budget -= cost
        self.budget_var.set(f"Orçamento: {self.budget}")

        # Atualiza o resultado na localização
        entry = f"{sensor}:{reading}"

        # Actualiza o histórico
        self.cell_history[(r, c)] = f"{self.cell_history.get((r, c), '')}\n{entry}".strip()
        self.history_log.config(state='normal')
        self.history_log.insert(tk.END, f"{sensor} em ({r},{c}): {reading}\n")
        self.history_log.see(tk.END)
        self.history_log.config(state='disabled')

        self.update_probabilities(sensor, reading, (r, c))
        self.update_grid_display()

    # actualiza as probabilidades no tabuleiro
    def update_probabilities(self, sensor, reading, click_loc):
        new_probs = np.zeros((ROWS, COLS))
        table_row = self.current_sensor_table[sensor][reading]
        max_idx = len(table_row) - 1

        for r in range(ROWS):
            for c in range(COLS):
                d = cityblock((r, c), click_loc)
                prob_evidence = table_row[min(d, max_idx)]
                new_probs[r, c] = self.probs[r, c] * prob_evidence

        total = np.sum(new_probs)
        if total > 0:
            self.probs = new_probs / total

    # Reinicia o jogo
    def reset_game(self):
        self.budget = self.INITIAL_BUDGET
        self.budget_var.set(f"Orçamento: {self.budget}")
        self.ark_loc = (random.randint(0, ROWS - 1), random.randint(0, COLS - 1))
        self.probs = np.full((ROWS, COLS), 1.0 / (ROWS * COLS))
        self.used_sensors = set()
        self.cell_history = {}

        self.history_log.config(state='normal')
        self.history_log.delete('1.0', tk.END)
        self.history_log.config(state='disabled')

        self.update_grid_display()


if __name__ == "__main__":
    root = tk.Tk()
    game = TreasureGame(root)
    root.mainloop()
