import tkinter as tk
from tkinter import ttk
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg


class PerronFrobeniusApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Perron-Frobenius Eigenvalue Demo")

        # Top frame for controls
        control_frame = ttk.Frame(root, padding=10)
        control_frame.pack(side=tk.TOP, fill=tk.X)

        self.button = ttk.Button(
            control_frame,
            text="Generate random matrix",
            command=self.update_plot
        )
        self.button.pack(side=tk.LEFT)

        # Text box for matrix display
        self.matrix_label = ttk.Label(control_frame, text="", justify="left", font=("Courier", 11))
        self.matrix_label.pack(side=tk.LEFT, padx=20)

        # Matplotlib figure
        self.fig, self.ax = plt.subplots(figsize=(6, 6))
        self.canvas = FigureCanvasTkAgg(self.fig, master=root)
        self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)

        self.update_plot()

    def generate_matrix(self):
        #m = np.random.randint(3,6)
        return np.random.randint(1, 10, size=(6, 6))

    def update_plot(self):
        A = self.generate_matrix()
        eigvals = np.linalg.eigvals(A)

        self.ax.clear()

        # Scatter plot of eigenvalues
        self.ax.scatter(eigvals.real, eigvals.imag, s=120, c="red")

        # Axes
        self.ax.axhline(0, linewidth=2)
        self.ax.axvline(0, linewidth=2)

        # Labels and title
        self.ax.set_xlabel("Real part")
        self.ax.set_ylabel("Imaginary part")
        self.ax.set_title("Eigenvalues in the complex plane")

        # Make plot limits adapt nicely
        #x = eigvals.real
        #y = eigvals.imag
        #margin = 1.0
        #self.ax.set_xlim(min(x) - margin, max(x) + margin)
        #self.ax.set_ylim(min(y) - margin, max(y) + margin)

        self.ax.set_ylim(-6, 6)
        self.ax.set_xlim(-10, 35)


        self.ax.set_aspect("equal", adjustable="box")
        self.ax.grid(True)

        # Show matrix
        matrix_text = "Matrix A =\n" + np.array2string(A, separator=", ")
        self.matrix_label.config(text=matrix_text)

        self.canvas.draw()


if __name__ == "__main__":
    root = tk.Tk()
    app = PerronFrobeniusApp(root)
    root.mainloop()