import sys
from sympy.external import import_module
matchpy = import_module("matchpy")

if not matchpy:
    #bin/test will not execute any tests now
    disabled = True

if sys.version_info[:2] < (3, 6):
    disabled = True

from sympy.integrals.rubi.rubimain import rubi_integrate
from sympy.functions import log, sqrt, exp, cos, sin, tan, sec, csc, cot
from sympy.functions.elementary.hyperbolic import atanh as arctanh
from sympy.functions.elementary.hyperbolic import asinh as arcsinh
from sympy.functions.elementary.hyperbolic import acosh as arccosh
from sympy.functions.elementary.trigonometric import atan as arctan
from sympy.functions.elementary.trigonometric import asin as arcsin
from sympy.functions.elementary.trigonometric import acos as arccos
from sympy.integrals.rubi.utility_function import EllipticE, EllipticF, EllipticPi, hypergeom, rubi_test, AppellF1
from sympy.core.numbers import (I, pi as Pi)
from sympy.core.singleton import S
from sympy.core.symbol import symbols
from sympy.functions.elementary.exponential import exp_polar
from sympy.functions.special.hyper import hyper
from sympy.integrals.integrals import Integral
from sympy.simplify.simplify import simplify
from sympy.testing.pytest import XFAIL

A, B, C, D, a, b, c, d, e, f, g, h, i, m, n, p, x, u = symbols('A B C D a b c d e f g h i m n p x u')

def test_1():
    '''
    Tests for Rubi Algebraic 1.2 rules. Parsed from Maple syntax
    All tests: http://www.apmaths.uwo.ca/~arich/IntegrationProblems/MapleSyntaxFiles/MapleSyntaxFiles.html
    Note: Some tests are commented since they depend rules other than Algebraic1.2.
    '''
    test = [
        [(a + b*x)**S(2)*(e + f*x)*sqrt(c + d*x)/x, x, S(5), S(2)/S(7)*f*(a + b*x)**S(2)*(c + d*x)**(S(3)/S(2))/d + S(2)/S(105)*(c + d*x)**(S(3)/S(2))*(S(2)*(S(10)*a**S(2)*d**S(2)*f - b**S(2)*c*(S(7)*d*e - S(4)*c*f) + S(7)*a*b*d*(S(5)*d*e - S(2)*c*f)) + S(3)*b*d*(S(7)*b*d*e - S(4)*b*c*f + S(4)*a*d*f)*x)/d**S(3) - S(2)*a**S(2)*e*arctanh(sqrt(c + d*x)/sqrt(c))*sqrt(c) + S(2)*a**S(2)*e*sqrt(c + d*x)],
        [(a + b*x)*(e + f*x)*sqrt(c + d*x)/x, x, S(4), - S(2)/S(15)*(c + d*x)**(S(3)/S(2))*(S(2)*b*c*f - S(5)*d*(b*e + a*f) - S(3)*b*d*f*x)/d**S(2) - S(2)*a*e*arctanh(sqrt(c + d*x)/sqrt(c))*sqrt(c) + S(2)*a*e*sqrt(c + d*x)],
        [(c + d*x)**S(2)*(e + f*x)*sqrt(a + b*x)/x, x, S(5), S(2)/S(7)*f*(a + b*x)**(S(3)/S(2))*(c + d*x)**S(2)/b + S(2)/S(105)*(a + b*x)**(S(3)/S(2))*(S(2)*(S(4)*a**S(2)*d**S(2)*f - S(7)*a*b*d*(d*e + S(2)*c*f) + S(5)*b**S(2)*c*(S(7)*d*e + S(2)*c*f)) + S(3)*b*d*(S(7)*b*d*e + S(4)*b*c*f - S(4)*a*d*f)*x)/b**S(3) - S(2)*c**S(2)*e*arctanh(sqrt(a + b*x)/sqrt(a))*sqrt(a) + S(2)*c**S(2)*e*sqrt(a + b*x)],
        [(c + d*x)*(e + f*x)*sqrt(a + b*x)/x, x, S(4), - S(2)/S(15)*(a + b*x)**(S(3)/S(2))*(S(2)*a*d*f - S(5)*b*(d*e + c*f) - S(3)*b*d*f*x)/b**S(2) - S(2)*c*e*arctanh(sqrt(a + b*x)/sqrt(a))*sqrt(a) + S(2)*c*e*sqrt(a + b*x)],
        [x**S(4)*(e + f*x)**n/((a + b*x)*(c + d*x)), x, S(8), e**S(2)*(e + f*x)**(S(1) + n)/(b*d*f**S(3)*(S(1) + n)) + (b*c + a*d)*e*(e + f*x)**(S(1) + n)/(b**S(2)*d**S(2)*f**S(2)*(S(1) + n)) + (b**S(2)*c**S(2) + a*b*c*d + a**S(2)*d**S(2))*(e + f*x)**(S(1) + n)/(b**S(3)*d**S(3)*f*(S(1) + n)) - S(2)*e*(e + f*x)**(S(2) + n)/(b*d*f**S(3)*(S(2) + n)) - (b*c + a*d)*(e + f*x)**(S(2) + n)/(b**S(2)*d**S(2)*f**S(2)*(S(2) + n)) + (e + f*x)**(S(3) + n)/(b*d*f**S(3)*(S(3) + n)) - a**S(4)*(e + f*x)**(S(1) + n)*hypergeom([S(1), S(1) + n], [S(2) + n], b*(e + f*x)/(b*e - a*f))/(b**S(3)*(b*c - a*d)*(b*e - a*f)*(S(1) + n)) + c**S(4)*(e + f*x)**(S(1) + n)*hypergeom([S(1), S(1) + n], [S(2) + n], d*(e + f*x)/(d*e - c*f))/(d**S(3)*(b*c - a*d)*(d*e - c*f)*(S(1) + n))],
        [(a + b*x)*(c + d*x)*(e + f*x)*(g + h*x), x, S(2), a*c*e*g*x + S(1)/S(2)*(b*c*e*g + a*(d*e*g + c*f*g + c*e*h))*x**S(2) + S(1)/S(3)*(b*(d*e*g + c*f*g + c*e*h) + a*(d*f*g + d*e*h + c*f*h))*x**S(3) + S(1)/S(4)*(a*d*f*h + b*(d*f*g + d*e*h + c*f*h))*x**S(4) + S(1)/S(5)*b*d*f*h*x**S(5)],
        [(a + b*x)*(c + d*x)*(e + f*x)/(g + h*x), x, S(2), (b*(d*g - c*h)*(f*g - e*h) - a*h*(d*f*g - d*e*h - c*f*h))*x/h**S(3) + S(1)/S(2)*(a*d*f*h - b*(d*f*g - d*e*h - c*f*h))*x**S(2)/h**S(2) + S(1)/S(3)*b*d*f*x**S(3)/h - (b*g - a*h)*(d*g - c*h)*(f*g - e*h)*log(g + h*x)/h**S(4)],
        [(a + b*x)**m*(c + d*x)*(e + f*x)*(g + h*x), x, S(2), (b*c - a*d)*(b*e - a*f)*(b*g - a*h)*(a + b*x)**(S(1) + m)/(b**S(4)*(S(1) + m)) + (S(3)*a**S(2)*d*f*h + b**S(2)*(d*e*g + c*f*g + c*e*h) - S(2)*a*b*(d*f*g + d*e*h + c*f*h))*(a + b*x)**(S(2) + m)/(b**S(4)*(S(2) + m)) - (S(3)*a*d*f*h - b*(d*f*g + d*e*h + c*f*h))*(a + b*x)**(S(3) + m)/(b**S(4)*(S(3) + m)) + d*f*h*(a + b*x)**(S(4) + m)/(b**S(4)*(S(4) + m))],
        [(c + d*x)**( - S(4) - m)*(e + f*x)**m*(g + h*x), x, S(3), - (d*g - c*h)*(c + d*x)**( - S(3) - m)*(e + f*x)**(S(1) + m)/(d*(d*e - c*f)*(S(3) + m)) + (c*f*h*(S(1) + m) + d*(S(2)*f*g - e*h*(S(3) + m)))*(c + d*x)**( - S(2) - m)*(e + f*x)**(S(1) + m)/(d*(d*e - c*f)**S(2)*(S(2) + m)*(S(3) + m)) - f*(c*f*h*(S(1) + m) + d*(S(2)*f*g - e*h*(S(3) + m)))*(c + d*x)**( - S(1) - m)*(e + f*x)**(S(1) + m)/(d*(d*e - c*f)**S(3)*(S(1) + m)*(S(2) + m)*(S(3) + m))],
    ]
    for i in test:
        r = rubi_integrate(i[0], i[1])
        if len(i) == 5:
            assert rubi_test(r, i[1], i[3], expand=True, _diff=True) or rubi_test(r, i[1], i[4], expand=True, _diff=True)
        else:
            assert rubi_test(r, i[1], i[3], expand=True, _diff=True)
@XFAIL
def test_2():
    test = [
        [x**m*(e + f*x)**n/((a + b*x)*(c + d*x)), x, S(6), b*x**(S(1) + m)*(e + f*x)**n*AppellF1(S(1) + m, - n, S(1), S(2) + m, - f*x/e, - b*x/a)/(a*(b*c - a*d)*(S(1) + m)*(S(1) + f*x/e)**n) - d*x**(S(1) + m)*(e + f*x)**n*AppellF1(S(1) + m, - n, S(1), S(2) + m, - f*x/e, - d*x/c)/(c*(b*c - a*d)*(S(1) + m)*(S(1) + f*x/e)**n)],
        [(a + b*x)**m*(c + d*x)**n*(e + f*x)*(g + h*x), x, S(3), - (a + b*x)**(S(1) + m)*(c + d*x)**(S(1) + n)*(b*c*f*h*(S(2) + m) + a*d*f*h*(S(2) + n) - b*d*(f*g + e*h)*(S(3) + m + n) - b*d*f*h*(S(2) + m + n)*x)/(b**S(2)*d**S(2)*(S(2) + m + n)*(S(3) + m + n)) + (a**S(2)*d**S(2)*f*h*(S(1) + n)*(S(2) + n) + a*b*d*(S(1) + n)*(S(2)*c*f*h*(S(1) + m) - d*(f*g + e*h)*(S(3) + m + n)) + b**S(2)*(c**S(2)*f*h*(S(1) + m)*(S(2) + m) - c*d*(f*g + e*h)*(S(1) + m)*(S(3) + m + n) + d**S(2)*e*g*(S(2) + m + n)*(S(3) + m + n)))*(a + b*x)**(S(1) + m)*(c + d*x)**n*hypergeom([S(1) + m, - n], [S(2) + m], - d*(a + b*x)/(b*c - a*d))/(b**S(3)*d**S(2)*(S(1) + m)*(S(2) + m + n)*(S(3) + m + n)*(b*(c + d*x)/(b*c - a*d))**n)],
        [(a + b*x)**m*(A + B*x)*(c + d*x)**n*(e + f*x)**p, x, S(7), (A*b - a*B)*(a + b*x)**(S(1) + m)*(c + d*x)**n*(e + f*x)**p*AppellF1(S(1) + m, - n, - p, S(2) + m, - d*(a + b*x)/(b*c - a*d), - f*(a + b*x)/(b*e - a*f))/(b**S(2)*(S(1) + m)*(b*(c + d*x)/(b*c - a*d))**n*(b*(e + f*x)/(b*e - a*f))**p) + B*(a + b*x)**(S(2) + m)*(c + d*x)**n*(e + f*x)**p*AppellF1(S(2) + m, - n, - p, S(3) + m, - d*(a + b*x)/(b*c - a*d), - f*(a + b*x)/(b*e - a*f))/(b**S(2)*(S(2) + m)*(b*(c + d*x)/(b*c - a*d))**n*(b*(e + f*x)/(b*e - a*f))**p)],
        [(A + B*x)*(c + d*x)**n*(e + f*x)**p/(a + b*x), x, S(5), - (A*b - a*B)*(c + d*x)**(S(1) + n)*(e + f*x)**p*AppellF1(S(1) + n, S(1), - p, S(2) + n, b*(c + d*x)/(b*c - a*d), - f*(c + d*x)/(d*e - c*f))/(b*(b*c - a*d)*(S(1) + n)*(d*(e + f*x)/(d*e - c*f))**p) - B*(c + d*x)**(S(1) + n)*(e + f*x)**(S(1) + p)*hypergeom([S(1), S(2) + n + p], [S(2) + p], d*(e + f*x)/(d*e - c*f))/(b*(d*e - c*f)*(S(1) + p)), - (A*b - a*B)*(c + d*x)**(S(1) + n)*(e + f*x)**p*AppellF1(S(1) + n, - p, S(1), S(2) + n, - f*(c + d*x)/(d*e - c*f), b*(c + d*x)/(b*c - a*d))/(b*(b*c - a*d)*(S(1) + n)*(d*(e + f*x)/(d*e - c*f))**p) + B*(c + d*x)**(S(1) + n)*(e + f*x)**p*hypergeom([S(1) + n, - p], [S(2) + n], - f*(c + d*x)/(d*e - c*f))/(b*d*(S(1) + n)*(d*(e + f*x)/(d*e - c*f))**p)],
        [(c*i + d*i*x)/(sqrt(c + d*x)*sqrt(e + f*x)*sqrt(g + h*x)), x, S(3), S(2)*i*EllipticE(sqrt(h)*sqrt(e + f*x)/sqrt( - f*g + e*h), sqrt( - d*(f*g - e*h)/((d*e - c*f)*h)))*sqrt( - f*g + e*h)*sqrt(c + d*x)*sqrt(f*(g + h*x)/(f*g - e*h))/(f*sqrt(h)*sqrt( - f*(c + d*x)/(d*e - c*f))*sqrt(g + h*x))],
        [(a + b*x)**m*(c + d*x)**n*(e + f*x)**p, x, S(3), (a + b*x)**(S(1) + m)*(c + d*x)**n*(e + f*x)**p*AppellF1(S(1) + m, - n, - p, S(2) + m, - d*(a + b*x)/(b*c - a*d), - f*(a + b*x)/(b*e - a*f))/(b*(S(1) + m)*(b*(c + d*x)/(b*c - a*d))**n*(b*(e + f*x)/(b*e - a*f))**p)],
        [(a + b*x)**m*(c + d*x)**n*(e + f*x)**p/(g + h*x), x, S(0), Integral((a + b*x)**m*(c + d*x)**n*(e + f*x)**p/(g + h*x), x)],
        [x**S(3)*(S(1) + a*x)/(sqrt(a*x)*sqrt(S(1) - a*x)), x, S(8), - S(75)/S(128)*arcsin(S(1) - S(2)*a*x)/a**S(4) - S(25)/S(32)*(a*x)**(S(3)/S(2))*sqrt(S(1) - a*x)/a**S(4) - S(5)/S(8)*(a*x)**(S(5)/S(2))*sqrt(S(1) - a*x)/a**S(4) - S(1)/S(4)*(a*x)**(S(7)/S(2))*sqrt(S(1) - a*x)/a**S(4) - S(75)/S(64)*sqrt(a*x)*sqrt(S(1) - a*x)/a**S(4)],
    ]
    for index in test:
        r = rubi_integrate(index[0], index[1])
        if len(index) == 5:
            assert rubi_test(r, index[1], index[3], expand=True, _diff=True) or rubi_test(r, index[1], index[4], expand=True, _diff=True)
        else:
            assert rubi_test(r, index[1], index[3], expand=True, _diff=True)

@XFAIL
def test_numerical():
    test = [
        #[S(1)/((a + b*x)*sqrt(c + d*x)*sqrt(e + f*x)*sqrt(g + h*x)), x, S(1), - S(2)*EllipticPi(sqrt( - f/(d*e - c*f))*sqrt(c + d*x), - b*(d*e - c*f)/((b*c - a*d)*f), sqrt((d*e - c*f)*h/(f*(d*g - c*h))))*sqrt(d*(e + f*x)/(d*e - c*f))*sqrt(d*(g + h*x)/(d*g - c*h))/((b*c - a*d)*sqrt( - f/(d*e - c*f))*sqrt(e + f*x)*sqrt(g + h*x))],
        #[S(1)/(sqrt(a + b*x)*sqrt(c + d*x)*sqrt(e + f*x)*sqrt(g + h*x)), x, S(2), - S(2)*(a + b*x)*sqrt(cos(arctan(sqrt(b*e - a*f)*sqrt(g + h*x)/(sqrt(f*g - e*h)*sqrt(a + b*x))))**S(2))/cos(arctan(sqrt(b*e - a*f)*sqrt(g + h*x)/(sqrt(f*g - e*h)*sqrt(a + b*x))))*EllipticF(sin(arctan(sqrt(b*e - a*f)*sqrt(g + h*x)/(sqrt(f*g - e*h)*sqrt(a + b*x)))), sqrt((d*e - c*f)*(b*g - a*h)/((b*e - a*f)*(d*g - c*h))))*sqrt(f*g - e*h)*sqrt((b*g - a*h)*(c + d*x)/((d*g - c*h)*(a + b*x)))*sqrt((b*g - a*h)*(e + f*x)/((f*g - e*h)*(a + b*x)))*sqrt(S(1) + (b*c - a*d)*(g + h*x)/((d*g - c*h)*(a + b*x)))/((b*g - a*h)*sqrt(b*e - a*f)*sqrt(c + d*x)*sqrt(e + f*x)*sqrt((S(1) + (b*c - a*d)*(g + h*x)/((d*g - c*h)*(a + b*x)))/(S(1) + (b*e - a*f)*(g + h*x)/((f*g - e*h)*(a + b*x))))*sqrt(S(1) + (b*e - a*f)*(g + h*x)/((f*g - e*h)*(a + b*x))))],
    ]

    for i in test:
        r = rubi_integrate(i[0], i[1])
        if len(i) == 5:
            assert rubi_test(r, i[1], i[3], expand=True, _diff=True, _numerical=True) or rubi_test(r, i[1], i[4], expand=True, _diff=True, _numerical=True)
        else:
            assert rubi_test(r, i[1], i[3], expand=True, _diff=True, _numerical=True)
