'''
Created on 4-Jan-2023

@author: bthakur

'''
import inspect
import traceback

import random
from xv.km.util import latex_fraction, latex_color
from xv.util import toIntOrFloat

from sympy import (Rational, sqrt, srepr, symbols, Symbol, limit, latex, Function,
                   Limit, oo, Derivative, Integral,
                   simplify, solve, expand,
                   exp, log, expand_log,
                   Mul, Add, Pow,
                   Sum, binomial, factorial, 
                   factor, sympify,
                   Eq, srepr
                   )

import sympy

from sympy import UnevaluatedExpr as ueval

from sympy import (acos, acot, acoth, acsc, asec, asin, 
                   asinh, atan, atan2, atanh, 
                   cos, cosh, cot, coth, csc, sec, 
                   sin, sinc, sinh, tan, tanh)


from xv.util import run_with_timeout

# _transform_helper
# TransformHelper


from xv.util import UtilClass

class TransformHelper(UtilClass):
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.a = symbols('a', constant = True) #, nonzero=True)
        self.b = symbols('b', constant = True)
        self.c = symbols('c', constant = True)
        self.n = symbols('n', constant = True)
        self.m = symbols('m', constant = True)
        
        self.u = symbols('u')
        self.x = symbols('x')
        self.y = symbols('y')
        self.z = symbols('z')
        pass
    
    def get_1_minus_xn_expr_dict(self):
        
        x = self.x
        n = symbols('n', integer = True, positive = True)
        
        m = random.choice([random.randint(2, 10), random.randint(11, 100), n])
        
        expr = 1 - x ** m

        factor_terms = [] 
        term0 = Symbol(f"\\left( {latex(1 - x)} \\right)")
        factor_terms.append(term0)
        
        strip_series = True
        max_term_count = 3
        try:
            if m <= max_term_count:
                strip_series = False
                max_term_count = m
        except:
            pass
        
        term1 = []
        for i in  range(max_term_count):
            term1.append(f"{latex(x ** i)}")
            pass
        
        if strip_series:
            term1.append(f"\\cdots")
            term1.append(f"{latex(x ** (m-2))}")
            term1.append(f"{latex(x ** (m-1))}")
        
        term1 = " + ".join(term1)
        term1 = Symbol(f"\\left( {term1} \\right)")
        factor_terms.append(term1)

        factors_0 = Symbol(f"{latex(term0)} {latex(term1)}")
        
        expr_dict = {}
        
        expr_dict['expr'] = expr
        expr_dict['factors_0'] = factors_0
        
        
        return expr_dict
        pass
    

    def get_binomial_expr_set(self):
        expr_sets = []
        
        x, y = [self.x, self.y]
        n = random.choice([2, 5, -1, -2, Rational(1, 2), Rational(-1, 2), self.n])
        plus_mius = random.choice([1, -1])
        
        expr_set = [x, y * plus_mius, n]
        expr_sets.append(expr_set)
        
        expr_set = [1, x * plus_mius, n]
        expr_sets.append(expr_set)
        
        expr_set = [1, plus_mius * 1 / x, n]
        expr_sets.append(expr_set)
        
        expr_set = [x, plus_mius * 1 / x, n]
        expr_sets.append(expr_set)
        
        v, c = symbols('v, c')
        
        expr_set = [1, - v**2 / c**2, Rational(-1, 2)]
        expr_sets.append(expr_set)
        
        
        return random.choice(expr_sets)
        pass


    def get_default_symbs(self, var_names):
        default_symbs = []
        for var_name in var_names:
            if hasattr(self, var_name):
                default_symbs.append(getattr(self, var_name))
            else:
                default_symbs.append(Symbol(var_name))
                pass
            pass
        return default_symbs
        pass

    def _modified_latex(self, expr, funct_symbs = None, mul_symbol = None):
        expr = self._convert_function_to_symbol(expr, funct_symbs = funct_symbs)
        expr_latex = latex(expr, mul_symbol = mul_symbol)
        
        expr_latex = expr_latex.replace("\\partial", "d")
        
        return expr_latex
        pass

    def _convert_function_to_symbol(self, expr, funct_symbs = None):
        if funct_symbs is None:
            funct_symbs = [self.y]
        
        temp_dict = {}
        for funct_symb in funct_symbs:
            temp_dict[funct_symb] = Symbol(funct_symb.name)
            pass
        
        if not temp_dict:
            return expr

        expr_subs = expr.subs(temp_dict)
        
        return expr_subs
        pass

    def _log_DELETED(self, sOut, to_print = None):
        if to_print is None:
            to_print = self.verbose
            
        if to_print:
            print(sOut)
            
    pass
#class TransformHelper:
