from .interfaz import *

SLIDER_INC = 0.01
TRIG_GRAPH_RESOLUTION = 100

class TrigonometriaCirculoFrame(TrigonometriaFrame):
    def __init__(self, controlador):
        self.controlador = controlador
        super().__init__(controlador)

        # 1. Inicialización de interfaz general
        self.setPanels(ejes=2, toolBar=False)

        # 2. Gráfica
        self._animating = False
        self.xLim = [-np.pi / 2, 3 * np.pi / 2]
        self.setCirculoGraph()
        self.setTrigGraph()

        # 3. Panel de interacción con la gráfica
        self.panelTiempo = tk.Frame(self.panelDown)
        self.panelTiempo.pack(fill='x', expand=True)
        tk.Label(self.panelTiempo, text='Tiempo\n(t)', font=TEXT_FONT, width=8).pack(side='left', padx=GRAL_PAD)
        self.sliderTiempo = tk.Scale(self.panelTiempo, from_=self.xLim[0], to=self.xLim[1], font=SLIDER_FONT, resolution=SLIDER_INC, orient='horizontal', command=self.__updateGraph)
        self.sliderTiempo.pack(side='left', fill='x', expand=True, padx=GRAL_PAD)
        self.sliderTiempo.set(1)
        self.panelAnimar = tk.Frame(self.panelDown)
        self.panelAnimar.pack(fill='x', expand=True)
        self.buttonAnimar = tk.Button(self.panelAnimar, text='Animar', font=TEXT_FONT, padx=GRAL_PAD, pady=GRAL_PAD, command=self.animar)
        self.buttonAnimar.pack()
        self.__updateGraph(init=True)

    def setTrigGraph(self):
        x = np.linspace(*self.xLim, TRIG_GRAPH_RESOLUTION)

        # Configuraciones
        self.ejes[1].set_xlim(self.xLim)
        self.ejes[1].set_ylim(-1.75, 1.75)
        self.ejes[1].set_title('Funciones trigonométricas')
        self.ejes[1].set_box_aspect(1)

        # Funciones trigonométricas
        self.sin_line, = self.ejes[1].plot(x, np.sin(x), label=rf'$\sin{{(t)}}={np.sin(self.t):.3g}$', color='red')
        self.cos_line, = self.ejes[1].plot(x, np.cos(x), label=rf'$\cos{{(t)}}={np.cos(self.t):.3g}$', color='blue')
        tanY = np.where(np.abs(np.tan(x)) > 10, np.nan, np.tan(x))
        self.tan_line, = self.ejes[1].plot(x, tanY, label=rf'$\tan{{(t)}}={np.tan(self.t):.3g}$', color='green')

        # Puntos (tiempo actual)
        self.sin_point, = self.ejes[1].plot([self.t], [np.sin(self.t)], marker='o', color='red')
        self.cos_point, = self.ejes[1].plot([self.t], [np.cos(self.t)], marker='o', color='blue')
        tanValue = np.tan(self.t) if abs(np.tan(self.t)) <= 10 else np.nan
        self.tan_point, = self.ejes[1].plot([self.t], [tanValue], marker='o', color='green')

        # Ticks en formato de radianes
        ticks = np.array([0, np.pi/2, np.pi, 3*np.pi/2])
        labels = [r'$0$', r'$\frac{\pi}{2}$', r'$\pi$', r'$\frac{3\pi}{2}$']
        self.ejes[1].set_xticks(ticks)
        self.ejes[1].set_xticklabels(labels)

        self.ejes[1].legend()

    def __updateGraph(self, _=None, *, init=False):
        self.t = self.sliderTiempo.get()
        self.updateCirculoGraph()
        self.updateTrigGraph()
        plt.legend()
        self.canvas.draw()

    def updateTrigGraph(self):
        # Puntos
        self.sin_point.set_data([self.t], [np.sin(self.t)])
        self.cos_point.set_data([self.t], [np.cos(self.t)])
        tanValue = np.tan(self.t) if abs(np.tan(self.t)) <= 10 else np.nan
        self.tan_point.set_data([self.t], [tanValue])

        # Textos
        self.sin_line.set_label(rf'$\sin{{(t)}}={np.sin(self.t):.3g}$')
        self.cos_line.set_label(rf'$\cos{{(t)}}={np.cos(self.t):.3g}$')
        self.tan_line.set_label(rf'$\tan{{(t)}}={np.tan(self.t):.3g}$')

    def __animationStep(self):
        if self._animating:
            nextT = self.t + SLIDER_INC
            if nextT >= self.xLim[1]:
                self.sliderTiempo.set(self.xLim[1])
                self._animating = False
                self.buttonAnimar.config(text='Animar')
                return
            self.t = nextT
            self.sliderTiempo.set(self.t)
            self._after_id = self.after(40, self.__animationStep)

    def animar(self):
        if self._animating: # Detención
            self._animating = False
            self.buttonAnimar.config(text='Animar')
        else: # Continuación
            self._animating = True
            self.buttonAnimar.config(text='Detener')
            self.__animationStep()

def main():
    app = Controlador(
        title='III. Funciones — Trigonometría y Círculo unitario',
        firstFrame=TrigonometriaCirculoFrame,
        height=700, width=1200
    )
    app.mainloop()

if __name__ == '__main__':
    main()
    
