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

RESOLUTION = 1000
MAX_X = 2 * pi

class TrigonometriaOperacionesBasicas(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 izquierdo
        self.panelDownLeft = tk.Frame(self.panelDown)
        self.panelDownLeft.pack(side='left', fill='x', expand=True)

        # 2.1.1. Droplist de operación
        panelOp = tk.Frame(self.panelDownLeft)
        panelOp.pack(side='right')
        self.opVar = tk.StringVar(value='suma')
        self.op = self.suma
        tk.Label(panelOp, text='Operación', font=TEXT_FONT, width=LABEL_GRAL_WIDTH).pack(side='top', padx=GRAL_PAD)
        self.menuOp = tk.OptionMenu(panelOp, self.opVar, 'suma', 'resta', 'doble', command=self.__updateOp)
        self.menuOp.config(font=TEXT_FONT)
        self.menuOp['menu'].config(font=TEXT_FONT)
        self.menuOp.pack(side='top', padx=GRAL_PAD)
        
        # 2.1.2. Slider de "a"
        panelA = tk.Frame(self.panelDownLeft)
        panelA.pack(side='top', fill='x', expand=True)
        tk.Label(panelA, text='a\n(grados)', font=TEXT_FONT, width=LABEL_GRAL_WIDTH).pack(side='left', padx=GRAL_PAD)
        self.sliderA = tk.Scale(panelA, from_=0, to=180, resolution=1, font=SLIDER_FONT, orient='horizontal', command=self.__updateA)
        self.sliderA.pack(side='left', fill='x', expand=True, padx=GRAL_PAD)
        self.sliderA.set(30)
        self.a = radians(30)

        # 2.1.3. Slider de "b"
        panelB = tk.Frame(self.panelDownLeft)
        panelB.pack(side='top', fill='x', expand=True)
        tk.Label(panelB, text='b\n(grados)', font=TEXT_FONT, width=LABEL_GRAL_WIDTH).pack(side='left', padx=GRAL_PAD)
        self.sliderB = tk.Scale(panelB, from_=0, to=180, resolution=1, font=SLIDER_FONT, orient='horizontal', command=self.__updateB)
        self.sliderB.pack(side='left', fill='x', expand=True, padx=GRAL_PAD)
        self.sliderB.set(30)
        self.b = radians(30)

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

    def __updateGraph(self, _=None, *, init=False):
        if init:
            self.xs = linspace(0, MAX_X, RESOLUTION)
            self.ejes.plot(self.xs, sin(self.xs), color='blue', label=r'$\sin{(x)}$')
            self.ejes.plot(self.xs, cos(self.xs), color='green', label=r'$\cos{(x)}$')
            self.lineA, = self.ejes.plot([self.a, self.a], [-1, 1], color='orange', linestyle='dashed', label=r'$a$')
            self.lineB, = self.ejes.plot([self.b, self.b], [-1, 1], color='purple', linestyle='dashed', label=r'$b$')
            titleOpAB, labelOpAB, opAB = self.op()
            self.lineOpAB, = self.ejes.plot([opAB, opAB], [-1, 1], color='red', linestyle='dashdot', label=rf'${labelOpAB}$')
            self.setLineasEjes(self.ejes)
            self.ejes.set_xlabel('X')
            self.ejes.set_ylabel('Y')
            self.ejes.grid(True)
            self.ejes.set_title(titleOpAB)
            plt.legend()
            plt.tight_layout()
        else:
            titleOpAB, labelOpAB, opAB = self.op()
            self.lineOpAB.set_data([opAB, opAB], [-1, 1])
            self.lineOpAB.set_label(rf'${labelOpAB}$')
            self.ejes.set_title(titleOpAB)
            plt.legend()
            self.canvas.draw()

    def __updateA(self, _=None):
        self.a = radians(self.sliderA.get())
        self.lineA.set_data([self.a, self.a], [-1, 1])
        self.__updateGraph()

    def __updateB(self, _=None):
        self.b = radians(self.sliderB.get())
        self.lineB.set_data([self.b, self.b], [-1, 1])
        self.__updateGraph()

    def __updateOp(self, _=None):
        match self.opVar.get():
            case 'suma':
                self.op = self.suma
            case 'resta':
                self.op = self.resta
            case 'doble':
                self.op = self.doble
        self.__updateGraph()

    def suma(self):
        return r'$\sin{(a+b)}=\sin{(a)}\cos{(b)}+\cos{(a)}\sin{(b)}$', 'a+b', self.a + self.b

    def resta(self):
        return r'$\sin{(a-b)}=\cos{(a)}\cos{(b)}+\sin{(a)}\sin{(b)}$', 'a-b', self.a - self.b

    def doble(self):
        return r'$\sin{(2a)}=2\sin{(a)}\cos{(a)}$', '2a', 2 * self.a

def main():
    app = Controlador(
        title='III. Funciones — Operaciones trigonométricas básicas',
        firstFrame=TrigonometriaOperacionesBasicas,
        height=800, width=775
    )
    app.mainloop()

if __name__ == '__main__':
    main()
