from .interfaz import *
from numpy import linspace, sin, pi
from sympy import symbols, sympify, solve, latex

SLIDER_MIN = 0
MAX_SPEED = 1000
RESOLUTION = 100
POS_HOR_SLIDER_INC = 0.1
SPEED_SLIDER_INC = 1
GRAVITY_SLIDER_INC = 0.01

class ProyectilFrame(SimpleInteractiveGraphFrame):
    def __init__(self, controlador):
        self.controlador = controlador
        super().__init__(controlador)
        
        # 1. Inicialización de interfaz general
        self.setPanels()

        # 2. Paneles de interacción con la gráfica
        # 2.1. Panel de posición horizontal
        self.panelHorPos = tk.Frame(self.panelDown)
        self.panelHorPos.pack(fill='x', expand=True)
        tk.Label(self.panelHorPos, text='Posición\nhorizontal', font=TEXT_FONT, width=LABEL_GRAL_WIDTH).pack(side='left', padx=GRAL_PAD)
        self.sliderHorPos = tk.Scale(self.panelHorPos, from_=0, to=1, resolution=0.01, orient='horizontal', command=self.__updatePosition)
        self.sliderHorPos.pack(side='left', fill='x', expand=True, padx=GRAL_PAD)
        self.sliderHorPos.set(0)

        # 2.2. Panel de velocidad inicial
        self.panelV0 = tk.Frame(self.panelDown)
        self.panelV0.pack(fill='x', expand=True)
        tk.Label(self.panelV0, text='Velocidad\ninicial (m/s)', font=TEXT_FONT, width=LABEL_GRAL_WIDTH).pack(side='left', padx=GRAL_PAD)
        self.sliderV0 = tk.Scale(self.panelV0, from_=0, to=MAX_SPEED, resolution=SPEED_SLIDER_INC, orient='horizontal', command=self.__updateGraph)
        self.sliderV0.pack(side='left', fill='x', expand=True, padx=GRAL_PAD)
        self.sliderV0.set(700)

        # 2.3. Panel de gravedad
        self.panelG = tk.Frame(self.panelDown)
        self.panelG.pack(fill='x', expand=True)
        tk.Label(self.panelG, text='Gravedad\n(m/s²)', font=TEXT_FONT, width=LABEL_GRAL_WIDTH).pack(side='left', padx=GRAL_PAD)
        self.sliderG = tk.Scale(self.panelG, from_=3.7, to=24.79, resolution=GRAVITY_SLIDER_INC, orient='horizontal', command=self.__updateGraph)
        self.sliderG.pack(side='left', fill='x', expand=True, padx=GRAL_PAD)
        self.sliderG.set(9.81)

        # 2.4. Panel de ángulo
        self.panelAngle = tk.Frame(self.panelDown)
        self.panelAngle.pack(fill='x', expand=True)
        tk.Label(self.panelAngle, text='Ángulo\n(grados)', font=TEXT_FONT, width=LABEL_GRAL_WIDTH).pack(side='left', padx=GRAL_PAD)
        self.sliderAngle = tk.Scale(self.panelAngle, from_=0, to=90, resolution=1, orient='horizontal', command=self.__updateGraph)
        self.sliderAngle.pack(side='left', fill='x', expand=True, padx=GRAL_PAD)
        self.sliderAngle.set(45)

        # 3. Gráfica
        self.__updateGraph(init=True)

    def h(self, *, t=None):
        v0 = self.sliderV0.get()
        g = self.sliderG.get()
        angle = self.sliderAngle.get() * pi / 180
        
        if t is None:
            t = symbols('t')
            self.sympyH = sympify(v0 * sin(angle) * t - 1 / 2 * g * t ** 2)
            self.latexH = latex(self.sympyH)
            self.tVuelo = solve(self.sympyH, t)[-1]
            times = linspace(0, self.tVuelo, RESOLUTION)
            t = times
            
        return t, v0 * sin(angle) * t - 1 / 2 * g * t**2

    def __updateGraph(self, _=None, *, init=False):
        if init:
            t, h = self.h()
            self.fig.suptitle(fr'${self.latexH}$')
            self.lineProyectil, = self.ejes.plot(t, h, color='black', linestyle='dashdot')
            self.pointPosition, = self.ejes.plot(0, 0, color='red', label=r'$(0, 0)$', linewidth=0)
            self.rocketPosition = self.ejes.text(0, 0, "🚀", fontsize=15, ha='center', va='center', fontname='Segoe UI Emoji')
            plt.axhline(0, color='red', linestyle='--')
            plt.axvline(0, color='red', linestyle='--')
            self.ejes.set_xlabel('Tiempo\n(segundos)')
            self.ejes.set_ylabel('Altura\n(metros)')
            self.ejes.grid(True)
            plt.tight_layout()
        else:
            t, h = self.h()
            self.fig.suptitle(rf'${self.latexH}$')
            self.lineProyectil.set_data(t, h)
            self.__updatePosition()

    def __updatePosition(self, _=None):
        horPos = self.sliderHorPos.get() * self.tVuelo
        t, h = self.h(t=horPos)
        self.pointPosition.set_data([t], [h])
        self.rocketPosition.set_position((t, h))
        self.pointPosition.set_label(rf'$({t:.3f}, {h:.3f})$')
        plt.legend()
        self.canvas.draw()

def main():
    app = Controlador(
        title='III. Funciones — Proyectil',
        firstFrame=ProyectilFrame,
        height=800, width=775
    )
    app.mainloop()

if __name__ == '__main__':
    main()
