from .interfaz import *
from numpy import linspace

RESOLUTION = 100

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

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

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

        # 3. Gráfica
        self.xLim = [-2, 2]
        self.__updateGraph(init=True)

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

    def __updateGraph(self, _=None, *, init=False):
        x = linspace(*self.xLim, RESOLUTION)
        y = self.f(x)
        minBound, maxBound = min(y), max(y)
        a = self.sliderPosHorizontal.get()
        b = self.f(a)

        if init:
            self.fig.suptitle(r'$(a, b) \in f \Leftrightarrow (b, a) \in f^{-1}$')
            self.ejes.set_xlabel('X')
            self.ejes.set_ylabel('Y')
            self.setLineasEjes(self.ejes)
            self.ejes.grid(True)

            # Funciones
            self.ejes.plot(x, y, label=r'$f(x)=x^{3} + 2$', color='black')
            self.ejes.annotate('', xy=(x[-1], y[-1]), xytext=(x[-2], y[-2]), arrowprops=dict(arrowstyle='->', color='black', lw=1))
            self.ejes.annotate('', xy=(x[0], y[0]), xytext=(x[1], y[1]), arrowprops=dict(arrowstyle='->', color='black', lw=1))
            self.ejes.plot([minBound, maxBound], [minBound, maxBound], label=r'$Id(x)=x$', color='red', linestyle='dashdot')
            self.ejes.plot(y, x, label=r'$f^{-1}(x)=\sqrt[3]{x - 2}$', color='green', linestyle='dashed')
            self.ejes.annotate('', xy=(y[-1], x[-1]), xytext=(y[-2], x[-2]), arrowprops=dict(arrowstyle='->', color='green', lw=1))
            self.ejes.annotate('', xy=(y[0], x[0]), xytext=(y[1], x[1]), arrowprops=dict(arrowstyle='->', color='green', lw=1))

            # Guía respecto a la posición horizontal
            self.guide, = self.ejes.plot([a, b, b], [b, b, a], color='red', linestyle='dotted', marker='.')
            self.cordenadaAB = self.ejes.text(a+POINT_TEXT_PAD, b+POINT_TEXT_PAD, rf'$({a:.3f}, {b:.3f})$', bbox=TEXT_BBOX)
            self.cordenadaBA = self.ejes.text(b+POINT_TEXT_PAD, a+POINT_TEXT_PAD, rf'$({b:.3f}, {a:.3f})$', bbox=TEXT_BBOX)
            
            plt.tight_layout()
        else:
            self.guide.set_data([a, b, b], [b, b, a])
            self.cordenadaAB.set_position((a+POINT_TEXT_PAD, b+POINT_TEXT_PAD))
            self.cordenadaAB.set_text(rf'$({a:.3f}, {b:.3f})$')
            self.cordenadaBA.set_position((b+POINT_TEXT_PAD, a+POINT_TEXT_PAD))
            self.cordenadaBA.set_text(rf'$({b:.3f}, {a:.3f})$')

        plt.legend()
        self.canvas.draw()

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

if __name__ == '__main__':
    main()
