# -*- coding: iso-8859-1 -*-
from __future__ import division # 1/2 == .5 (par defaut, 1/2 == 0)

import re

from customtest import *
from mathlib import traduire_formule
from mathlib.parsers import NBR, NBR_SIGNE, VAR, VAR_NOT_ATTR, NBR_OR_VAR, _arguments_latex

liste_fonctions = [key for key in mathlib.universal_functions.__dict__.keys() if "_" not in key]
liste_fonctions.append("limite")
liste_fonctions.append("log10")

class TestMathlibParsers(CustomTest):

    def assert_formule(self, x, y, OOo, LaTeX):
        y_ = traduire_formule(x, fonctions = liste_fonctions, OOo = OOo, LaTeX = LaTeX, verbose = False)
        if y_ != y:
            print "/!\\ Formule: ", x
            traduire_formule(x, fonctions = liste_fonctions, OOo = OOo, LaTeX = LaTeX, verbose = True)
            print "ERREUR: ",  y_, " != ", y
        self.assert_(y_ == y)

    def assert_arg_latex(self, x, *y):
        x = _arguments_latex(x, 2)
        y = list(y)
        if x != y:
            print "ERREUR (_arguments_latex): ", x, " != ",  y
        self.assert_(x == y)

    def assert_all(self, x, y):
        self.assert_formule(x, y, OOo = True, LaTeX = False)
        self.assert_formule(x, y, OOo = True, LaTeX = False)
        self.assert_formule(x, y, OOo = False, LaTeX = True)
        self.assert_formule(x, y, OOo = True, LaTeX = True)

    def assert_OOo(self, x, y):
        self.assert_formule(x, y, OOo = True, LaTeX = False)
        self.assert_formule(x, y, OOo = True, LaTeX = True)

    def assert_latex(self, x, y):
        self.assert_formule(x, y, OOo = False, LaTeX = True)
        self.assert_formule(x, y, OOo = True, LaTeX = True)

    def assert_match(self, pattern, chaine):
        u"""Teste si la chaine correspond entièrement au pattern."""
        self.assert_(re.match(pattern + "$", chaine))

    def assert_not_match(self, pattern, chaine):
        u"""Teste si la chaine ne correspond pas entièrement au pattern."""
        self.assert_(not re.match(pattern + "$", chaine))

    def assert_VAR(self, chaine):
        self.assert_match(VAR, chaine)
        self.assert_match(NBR_OR_VAR, chaine)

    def assert_not_VAR(self, chaine):
        self.assert_not_match(VAR, chaine)

    def assert_NBR(self, chaine):
        self.assert_match(NBR, chaine)
        self.assert_match(NBR_OR_VAR, chaine)

    def assert_NBR(self, chaine):
        self.assert_match(NBR, chaine)
        self.assert_match(NBR_SIGNE, chaine)
        self.assert_match(NBR_OR_VAR, chaine)

    def assert_NBR_SIGNE(self, chaine):
        self.assert_match(NBR_SIGNE, chaine)
        self.assert_not_match(NBR_OR_VAR, chaine)

    def assert_find_VAR_NOT_ATTR(self, chaine):
        self.assert_(re.search(VAR_NOT_ATTR, chaine))

    def assert_not_find_VAR_NOT_ATTR(self, chaine):
        self.assert_(not re.search(VAR_NOT_ATTR, chaine))

    def assert_not_NBR(self, chaine):
        self.assert_not_match(NBR, chaine)

    def test_tous_modes(self):
        self.assert_all("2x+3", "2*x+3")
        self.assert_all("2(x+3)", "2*(x+3)")
        self.assert_all("(x+1)x(x+3)", "(x+1)*x*(x+3)")
        self.assert_all("sin(x+1)x(x+3)", "sin(x+1)*x*(x+3)")
        self.assert_all("(x+1)cos(x+3)", "(x+1)*cos(x+3)")
        self.assert_all("-1.5x^(-2)+ab+3ab(2x+y)+x(y(z+1)))2(x)", "-1.5*x**(-2)+ab+3*ab*(2*x+y)+x*(y*(z+1)))*2*(x)")
        self.assert_all(u"3x³-2x²y-2x==5y", "3*x**3-2*x**2*y-2*x==5*y")
        self.assert_all(u"25%*12 mod 5", "25/100*12%5")
        self.assert_all(u"(25%*12)mod 5", "(25/100*12)%5")
        self.assert_all(u"limite(1/x^3,x,1+)", "limite(1/x**3,x,1,'+')")
        self.assert_all(u"limite(1/x^3,x, 1-  )", "limite(1/x**3,x,1,'-')")
        self.assert_all(u"x sin x+1", "x*sin(x)+1")
        self.assert_all(u"log10 ab y sin 2x+1", "log10(ab)*y*sin(2*x)+1")
        self.assert_all(u"cos 3.5x(x+1)", "cos(3.5*x)*(x+1)")
        self.assert_all(u"cos 2", "cos(2)")
        # Cas particulier :
        self.assert_all(u"cos -3", "cos-3")
        # Développement décimal infini périodique
        self.assert_all(u"17.03[45]", u"((1703+45/99)/100)")
        self.assert_all(u"17.[045]", u"((17+45/999)/1)")
        self.assert_all(u"17.1[0]", u"((171+0/9)/10)")
        # Ne pas rajouter de * devant les parenthèses d'une méthode
        self.assert_all(u"A.transpose()", u"A.transpose()")

    def test_mode_OOo(self):
        self.assert_OOo("2 times 3", "2*3")
        self.assert_OOo("2 over 3", "2/3")
        self.assert_OOo("{2+5x} over {3-x}", "(2+5*x)/(3-x)")
        self.assert_OOo("{2-.5x}over{3-x}", "(2-.5*x)/(3-x)")
        self.assert_OOo("0.85 sup {1 over 7} - 1", "0.85**(1/7)-1")


    def test_mode_LaTeX(self):
        self.assert_latex("2\\times3", "2*3")
        self.assert_latex("\\cos x\\sin x\\exp x", "cos(x)*sin(x)*exp(x)")
        self.assert_latex("\\frac{2}{3}", "((2)/(3))")
        self.assert_latex("\\frac{2+x}{3}", "((2+x)/(3))")
        self.assert_latex("\\dfrac{2+x}{1-3}", "((2+x)/(1-3))")
        self.assert_latex("\\tfrac{2+x}{3}", "((2+x)/(3))")
        self.assert_latex("\\dfrac{2x^2+x-7}{6-4x}", "((2*x**2+x-7)/(6-4*x))")
        self.assert_latex("-\\frac12-\\dfrac4{(6-4x)^2}", "-(1/2)-(4/((6-4*x)**2))")
        self.assert_latex("\\left((1+10~\\%)(1+5~\\%)(1-7~\\%)\\right)^{\\frac{1}{3} }", "((1+10/100)*(1+5/100)*(1-7/100))**(((1)/(3)))")
        self.assert_latex("\\text{0.7}\\times (-50)^2-9\\times (-50)+200", "(0.7)*(-50)**2-9*(-50)+200")
        self.assert_latex("\\ln(2)+\\exp(3)+\\log(\\pi+1)", "ln(2)+exp(3)+log(pi+1)")
        self.assert_latex("x\ge1\le3", "x>=1<=3")
        self.assert_latex(r"100\left(\left(1+\dfrac{50}{100}\right)^\frac{1}{10}-1\right)", "100*((1+((50)/(100)))**((1)/(10))-1)")

    def test_NBR(self):
        self.assert_NBR_SIGNE("-2.56")
        self.assert_NBR_SIGNE("-.56")
        self.assert_NBR_SIGNE("+5.")
        self.assert_NBR_SIGNE("+5.056")
        self.assert_NBR("56")
        self.assert_NBR(".46")
        self.assert_NBR("752.")
        self.assert_NBR("740.54")
        self.assert_not_NBR("5-6")
        self.assert_not_NBR(".")

    def test_VAR(self):
        self.assert_VAR("Arertytre")
        self.assert_VAR("a")
        self.assert_VAR("_")
        self.assert_VAR("_45ui")
        self.assert_VAR("A13")
        self.assert_not_VAR("1A")
        self.assert_not_VAR("2")

    def test_search_VAR_NOT_ATTR(self):
        self.assert_find_VAR_NOT_ATTR("a")
        self.assert_find_VAR_NOT_ATTR("1+_arrt9876")
        self.assert_find_VAR_NOT_ATTR("5*t_566")
        self.assert_find_VAR_NOT_ATTR("(_.t)/3")
        self.assert_not_find_VAR_NOT_ATTR(".aert")
        self.assert_not_find_VAR_NOT_ATTR("4.tyu+4")
        self.assert_not_find_VAR_NOT_ATTR("89eeazt")
        self.assert_not_find_VAR_NOT_ATTR("2-._ez")

    def test_arguments_LaTeX(self):
        self.assert_arg_latex('2{x+1}+4', '2', '{x+1}', '+4')
        self.assert_arg_latex('{x+2}5+4x-17^{2+x}', '{x+2}', '5', '+4x-17^{2+x}')


if __name__ == '__main__':
    unittest.main()
