from .interfaz import *
from numpy import linspace, sin, cos, tan, pi, nan, abs
from sympy import symbols, sympify, solve, latex

RESOLUTION = 1000

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

        # 2. Paneles de interacción con la gráfica
        # 2.1. Panel de posición vertical (a)
        self.panelVertPos = tk.Frame(self.panelDown)
        self.panelVertPos.pack(side='left', fill='x', expand=True)
        tk.Label(self.panelVertPos, text='Posición\nvertical', font=TEXT_FONT, width=LABEL_GRAL_WIDTH).pack(side='left', padx=GRAL_PAD)
        self.sliderVertPos = tk.Scale(self.panelVertPos, from_=-1, to=1, font=SLIDER_FONT, resolution=0.01, orient='horizontal', command=self.__updatePosition)
        self.sliderVertPos.pack(side='left', fill='x', expand=True, padx=GRAL_PAD)
        self.sliderVertPos.set(0)
        self.vertPos = 0
        
        # 2.2. Panel de selección de función
        self.panelOp = tk.Frame(self.panelDown)
        self.panelOp.pack(side='left')
        self.funcionVar = tk.StringVar(self.panelDown)
        self.funcionVar.set('Seno')
        self.funcion = sin
        self.labelFuncion = r'$y=\sin{(x)}$'
        menuFuncion = tk.OptionMenu(self.panelDown, self.funcionVar, 'Seno', 'Coseno', 'Tangente', command=self.__cambioFuncion)
        menuFuncion.config(font=TEXT_FONT)
        menuFuncion['menu'].config(font=TEXT_FONT)
        menuFuncion.pack(side='left', padx=GRAL_PAD)

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

    def __updateGraph(self, _=None, *, init=False):
        if init:
            self.xs = linspace(-2*pi, 2*pi, RESOLUTION)
            ys = self.funcion(self.xs)
            ys[abs(ys) > 2] = nan
            self.lineFuncion, = self.ejes.plot(self.xs, ys, color='blue', label=self.labelFuncion)
            self.lineHor, = self.ejes.plot([-2*pi, 2*pi], [self.vertPos, self.vertPos], color='red', label=r'$y=0$')
            self.setLineasEjes(self.ejes)
            self.ejes.set_xlabel('X\n(radianes)')
            self.ejes.set_ylabel('Y')
            self.ejes.set_xticks([n * np.pi / 2 for n in range(-4, 5)])
            self.ejes.set_xticklabels([r'$-2\pi$', r'$-\frac{3\pi}{2}$', r'$-\pi$', r'$-\frac{\pi}{2}$', r'$0$', r'$\frac{\pi}{2}$', r'$\pi$', r'$\frac{3\pi}{2}$', r'$2\pi$'])
            self.ejes.grid(True)
            plt.legend()
            plt.tight_layout()
        else:
            ys = self.funcion(self.xs)
            ys[abs(ys) > 2] = nan
            self.lineFuncion.set_data(self.xs, ys)
            self.lineFuncion.set_label(self.labelFuncion)
            self.lineHor.set_data([-2*pi, 2*pi], [self.vertPos, self.vertPos])
            self.lineHor.set_label(rf'$y={self.vertPos}$')
            plt.legend()
            self.canvas.draw()

    def __cambioFuncion(self, _):
        match self.funcionVar.get():
            case 'Seno':
                 self.funcion = sin
                 self.labelFuncion = r'$y=\sin{(x)}$'
            case 'Coseno':
                self.funcion = cos
                self.labelFuncion = r'$y=\cos{(x)}$'
            case 'Tangente':
                self.funcion = tan
                self.labelFuncion = r'$y=\tan{(x)}$'
        self.__updateGraph()

    def __updatePosition(self, _=None):
        self.vertPos = self.sliderVertPos.get()
        self.__updateGraph()

def main():
    app = Controlador(
        title='III. Funciones — Ecuación trigonométrica y Recta horizontal',
        firstFrame=TrigonometriaRectaHorizontalFrame,
        height=700, width=800
    )
    app.mainloop()

if __name__ == '__main__':
    main()
