from .interfaz import *
from numpy import linspace, sin

RESOLUTION = 100
SLIDER_INC = 0.01

class ComposicionFrame(SimpleInteractiveGraphFrame):
    def __init__(self, controlador):
        self.controlador = controlador
        super().__init__(controlador)

        # 1. Inicialización de interfaz general
        self.setPanels()

        # 2. Panel de interacción con la gráfica
        self.panelDeform = tk.Frame(self.panelDown)
        self.panelDeform.pack(fill='x', expand=True)
        tk.Label(self.panelDeform, text='Deformación', font=TEXT_FONT, width=LABEL_GRAL_WIDTH).pack(side='left', padx=GRAL_PAD)
        self.sliderDeform = tk.Scale(self.panelDeform, from_=0, to=1, resolution=SLIDER_INC, font=SLIDER_FONT, orient='horizontal', command=self.__updateGraph)
        self.sliderDeform.pack(side='left', fill='x', expand=True, padx=GRAL_PAD)
        self.sliderDeform.set(0)

        # 3. Gráfica
        self.xLim = [-2, 2]
        self.__updateGraph(init=True)
        self.ejes.callbacks.connect('xlim_changed', self.__updateXLim)        

    def f(self, x):
        return x**2

    def g(self, x):
        return sin(x)**2

    def transition(self, x):
        self.alpha = self.sliderDeform.get()
        return (1 - self.alpha) * self.f(x) + self.alpha * self.g(x)

    def __updateGraph(self, _=None, *, init=False):
        x = linspace(*self.xLim, RESOLUTION)

        if init:
            self.setLineasEjes(self.ejes)
            self.ejes.set_xlabel('X')
            self.ejes.set_ylabel('Y')
            self.ejes.grid(True)
            self.fLine, = self.ejes.plot(x, self.f(x), label=r'$f(x)=x^{2}$', color='blue', linestyle='dashdot')
            self.transitionLine, = self.ejes.plot(x, self.transition(x), color='black')
            self.gLine, = self.ejes.plot(x, self.g(x), label=r'$g(x)=\sin^{2}{(x)}$', color='red', linestyle='dashdot')
            plt.tight_layout()
            self.__updateXLim()
        else:
            self.transitionLine.set_data(x, self.transition(x))
            self.transitionLine.set_label(r'$h(x)=x^{2}$' if self.alpha == 0 else r'$h(x)=sin^{2}{(x)}$' if self.alpha == 1 else rf'$h(x)={1 - self.alpha:.3f}x^{2} + {self.alpha:.3f}\sin^{2}{{(x)}}$')

        plt.legend()
        self.canvas.draw()
    
    def __updateXLim(self, _=None):
        self.xLim = self.ejes.get_xlim()

        # Modificación de las gráficas fijas
        x = linspace(*self.xLim, RESOLUTION)
        self.fLine.set_data(x, self.f(x))
        self.gLine.set_data(x, self.g(x))
        
        self.__updateGraph()

def main():
    app = Controlador(
        title='III. Funciones — Composición',
        firstFrame=ComposicionFrame,
        height=800, width=775
    )
    app.mainloop()

if __name__ == '__main__':
    main()
