from sympy import Symbol, lambdify
from os import system, remove
from os.path import exists
from math import atan, pi

class Graphique_suite:
    def __init__(self,fonction,n,u0,xmin,xmax,ymin,ymax,stepgrid=0.2,xscale=1,yscale=1,valwidth=40,Df=None):
        self.fonction = fonction
        x = Symbol('x')
        self.f = lambdify(x,self.fonction,'math')
        self.xmin = xmin
        self.xmax = xmax
        self.ymin = ymin
        self.ymax = ymax
        self.stepgrid = stepgrid
        self.xscale = xscale
        self.yscale = yscale
        self.valwidth = valwidth
        if Df == None:
            self.Df = [ xmin , xmax ]
        else:
            self.Df = Df
        self.u0 = u0
        self.n = n
        self.U = [ (0,self.u0) ] # self.U = liste des termes successifs (k,u(k))
        for k in range(1,self.n):
            self.U.append( ( k , self.f(self.U[k-1][1]) ) )
        
    def graphique_tex(self,values):
        tex = '\\documentclass{standalone}\n'
        tex += '\\usepackage{tikz}\n'
        tex += '\\begin{document}\n'
        tex += '\\begin{tikzpicture}[baseline='+str((self.ymax-0.2)*self.yscale)+'cm,xscale='+str(self.xscale)+',yscale='+str(self.yscale)+']\n'
        tex += f'\\draw[dotted,gray,opacity=0.5] ({self.xmin},{self.ymin}) grid[step={self.stepgrid}] ({self.xmax},{self.ymax});\n'
        tex += f'\\draw[gray,opacity=0.5] ({self.xmin},{self.ymin}) grid ({self.xmax},{self.ymax});\n'
        tex += f'\\draw[thick,->,>=latex] ({self.xmin},0) -- ({self.xmax},0);\n'
        tex += f'\\draw[thick,->,>=latex] (0,{self.ymin}) -- (0,{self.ymax});\n'
        tex += f'\\clip ({self.xmin},{self.ymin}) rectangle ({self.xmax},{self.ymax});\n'
        tex += f'\\draw[thick,orange] plot[domain={self.xmin}:{self.xmax}] '
        tex += '(\\x,\\x) node[below left,rotate='+str(180*atan(self.yscale/self.xscale)/pi)+',scale=0.7,outer xsep=3mm] {$y=x$};\n'
        tex += '\\draw[thick,red] plot[domain='+str(self.Df[0])+':'+str(self.Df[1])+',samples=100] (\\x,{'+self.fonction.replace('x','\\x')+'});\n'
        tex += '% Graduation des axes\n'
        
        for a in range(int(self.xmin),int(self.xmax)+1):
            if a != 0:
                tex += f'\\draw[thick] ({a},0.1/{self.yscale}) -- ({a},-0.1/{self.yscale}) node[below,outer sep=2mm] '
                tex += '{' + str(a) + '};\n'
        for a in range(int(self.ymin),int(self.ymax)+1):
            if a != 0:
                tex += f'\\draw[thick] (0.1/{self.xscale},{a}) -- (-0.1/{self.yscale},{a}) node[left] '
                tex += '{' + str(a) + '};\n'
    
        for k in range(self.n-1):
            tex += f"\\draw[dashed,purple] ({self.U[k][1]},0) node[below,scale=0.5,outer ysep=3mm] " +  '{$u_{'+str(k)+'}$} -- '
            tex += f"({self.U[k][1]},{self.U[k+1][1]});\n"
            tex += f"\\draw[dashed,purple] ({self.U[k][1]},{self.U[k+1][1]}) -- ({self.U[k+1][1]},{self.U[k+1][1]});\n"
            tex += f"\\draw[dashed,purple] ({self.U[k+1][1]},{self.U[k+1][1]}) -- ({self.U[k+1][1]},0);\n"
            
        tex += f"\\node[below,scale=0.5,outer ysep=3mm,purple] at ({self.U[k+1][1]},0) "
        tex += '{$u_{'+str(self.n-1)+'}$};\n%\n'        
        tex += '\\end{tikzpicture}\n'
        
        if values:
            tex += '\\begin{minipage}[t]{'+str(self.valwidth)+'mm}\n'
            for v in self.U:
                tex += '$u_{'+ str(v[0]) + '} = ' + str(v[1]) + '$\\\\\n'
            tex += '\\end{minipage}\n'
        
        tex += '\\end{document}'
    
        return tex
    
    def exportPdf(self,name,values=False):
        if exists(f'{name}.tex'):
            remove(f'{name}.tex')
            
        fichier = open(f"{name}.tex","x")
        fichier.write(self.graphique_tex(values))
        fichier.close()

        system(f"pdflatex {name}.tex")
        system(f"START {name}.pdf")

G = Graphique_suite( fonction = 'sqrt(x+6)', \
                     n = 5 , \
                     u0 = 10, \
                     xmin = -8, \
                     xmax = 12, \
                     ymin = -1,\
                     ymax = 5, \
                     stepgrid = 0.2, \
                     xscale = 1, \
                     yscale = 1,\
                     valwidth = 50, \
                     Df = [-6,12])

G.exportPdf('essai' , values = False)

