'''
Created on 26-Jan-2024

@author: bthakur
'''


import random
from sympy import (Symbol, symbols, sympify, simplify,
                   latex, UnevaluatedExpr as ueval,
                   Rational,
                  )



import inspect
import traceback
import random
import numpy as np


from xv.km.util import latex_fraction

from xv.km.ui import SvgHelper
from xv.util.data import CacheUtil
import matplotlib.pyplot as plt

from ...util import MathUtil
from xv.util import UtilClass


# _arithmetic_expression_solver
# ArithmeticExpressionSolver

class ArithmeticExpressionSolver(UtilClass):
    '''
    This is a newer solver 
    '''
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        
        pass
    
    def get_soluton(self, expr_recs):
        expr_recs = list(reversed(expr_recs))
        expr_in_prob = expr_recs[0]['expr_ueval']
        
        prob_s = f"""
        Solve $\displaystyle {latex(expr_in_prob, mul_symbol='times')}$
        """

        soln_stmts = []
        
        soln_stmt = f"""
        $\displaystyle {latex(expr_in_prob, mul_symbol='times')}$
        """
        soln_stmts.append(soln_stmt.strip())
        
        
        expr = None
        for idx, expr_rec in enumerate(expr_recs):
            if idx == 0:
                expr = expr_rec['expr_ueval']
                if self.verbose:
                    self.display_stmt(expr, to_latex = True, show_type = False)
            else:
                expr_latex = expr_rec['expr_latex']
                expr_ueval = expr_rec['expr_ueval']
                mod_expr = sympify(expr).subs(expr_latex, expr_ueval)
                #display_stmt(mod_expr)
                expr = mod_expr
    
            sub_expr_latex = expr_rec['sub_expr_latex']
            sub_expr = expr_rec['sub_expr']
            #mod_expr_ueval = sympify(expr).subs(sub_expr_latex, ueval(sub_expr))
            mod_expr = sympify(expr).subs(sub_expr_latex, sub_expr)

            soln_stmt = f"""
            $\\displaystyle 
            = {latex(mod_expr, mul_symbol='times')} \\qquad 
            \\color{{red}}{{ \\text {{ as }} 
            {latex(sub_expr_latex, mul_symbol='times')} 
            = {latex(sub_expr, mul_symbol='times')}  }}
            $
            """
            soln_stmts.append(soln_stmt.strip())
            
            expr = mod_expr
            pass
        
        if self.verbose:
            self.display_stmt(expr, to_latex = True, show_type = True)
        
        expr_simplified = simplify(expr)

        soln_stmt = f"""
        $\displaystyle = {latex(expr_simplified, mul_symbol='times')}$
        """
        soln_stmts.append(soln_stmt.strip())
        
        soln_s = "\n\n".join(soln_stmts)
        
        answer_s = f"""
        $\displaystyle {latex(expr_simplified, mul_symbol='times')}$
        """
                
        result = {
            'expr': expr_in_prob,
            'expr_simplified': expr_simplified,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        
        return result 
        pass
    
    
    def get_random_expr_data(self):
        expr_recs = []
        
        max_loop = random.randint(3, 6)
        while len(expr_recs) < max_loop :
            sub_expr, sub_expr_latex = self.get_sub_expr()
    
            if len(expr_recs) == 0:
                expr, expr_latex = sub_expr, sub_expr_latex
            else:
                prev_expr_rec = expr_recs[-1]
                prev_expr, prev_expr_latex = prev_expr_rec['expr'], prev_expr_rec['expr_latex']
                expr, expr_latex = self.get_next_expr(prev_expr, prev_expr_latex, sub_expr, sub_expr_latex)
                
    
            expr_rec = {
                'sub_expr_latex': sub_expr_latex,
                'sub_expr': sub_expr, 
                'expr_latex': expr_latex,
                'expr_ueval': expr, 
                'expr': sympify(expr).subs(sub_expr_latex, sub_expr)
            }
            
            if self.verbose:
                self.disp_expr_rec(expr_rec, len(expr_recs))
                pass
                
            expr_recs.append(expr_rec)
            pass
        return expr_recs
        pass


    def get_next_expr(self, expr, expr_latex, sub_expr, sub_expr_latex):
        expr_symb = Symbol(f"{expr_latex}")
        
        
        random_choice = random.randint(1, 8)
        if random_choice == 1:
            expr = expr_symb + sub_expr_latex
            expr_latex = f"{latex(expr_symb)} + {latex(sub_expr_latex)}"
            pass
        elif random_choice == 2:
            expr = sub_expr_latex + expr_symb
            expr_latex = f"{latex(sub_expr_latex)} + {latex(expr_symb)}"
            pass
        elif random_choice == 3:
            expr = expr_symb - sub_expr_latex
            expr_latex = f"{latex(expr_symb)} - {latex(sub_expr_latex)}"
            pass
        elif random_choice == 4:
            expr = sub_expr_latex - expr_symb
            expr_latex = f"{latex(sub_expr_latex)} - {latex(expr_symb)}"
            pass
        elif random_choice == 5:
            expr = expr_symb * sub_expr_latex
            expr_latex = f"{latex(expr_symb)} \\times {latex(sub_expr_latex)}"
            pass
        elif random_choice == 6:
            expr = sub_expr_latex * expr_symb
            expr_latex = f"{latex(sub_expr_latex)} \\times {latex(expr_symb)}"
            pass
        elif random_choice == 7:
            expr = ueval(expr_symb) / sub_expr_latex
            expr_latex = f"\\frac {{ {latex(expr_symb)} }}  {{ {latex(sub_expr_latex)} }}"
            pass
        elif random_choice == 8:
            expr = ueval(sub_expr_latex) / expr_symb
            expr_latex = f"\\frac {{ {latex(sub_expr_latex)} }} {{ {latex(expr_symb)} }}"
            pass
        else:
            expr = expr_symb + sub_expr_latex
            expr_latex = f"{latex(expr_symb)} + {latex(sub_expr_latex)}"
            pass
        return expr, Symbol(expr_latex)
        pass

    def disp_expr_rec(self, expr_rec, idx):
        try:
            from IPython.display import display, HTML
        except:
            display = print
            HTML = str
        
        print(f"idx = {idx}")
        for k,v in expr_rec.items():
            s = f"{k}: $\\displaystyle {latex(v)} $ &emsp;&emsp; ({type(v).__name__})"
            display(HTML(f"{s}<br/>"))
            pass
        print(f""" {'-' * 75} \n\n """)
        pass

    def display_stmt(self, s, to_latex = False, is_latex = True, show_type = True):
        try:
            from IPython.display import display, HTML
        except:
            display = print
            HTML = str
        
        if to_latex:
            s = f"{latex(s)}"
            is_latex = True
        
        if show_type:
            if to_latex:
                s = f"\\text{{ {type(s).__name__} }} = \\;\\; {s}"
            else:
                s = f"{type(s).__name__} = &nbsp;&nbsp; {s}"
                
        
        if is_latex:
            display(HTML(f"$\\displaystyle {s} $<br/>"))
        else:
            display(HTML(f"{s}<br/>"))
            
        pass



    def get_sub_expr(self):
        num1 = random.randint(2, 9) 
        num2 = random.randint(2, 9) * random.choice([1, -1])
            
        while True:
            num2 = random.randint(2, 9) * random.choice([1, -1])
            if num1 == num2:
                continue
                
            sub_expr = random.choice([
                [num1 + num2, f"{latex(num1)} + {latex(num2)}"],
                [num1 - num2, f"{latex(num1)} - {latex(num2)}"],
                [num1 * num2, f"{latex(num1)} \\times {latex(num2)}"],
                [Rational(num1, num2), f"\\frac {{ {latex(num1)} }} {{ {latex(num2)} }} "],
                                  ])
            if sub_expr[0] == 0:
                continue
                
            if sub_expr[0] < 0 or "+" in sub_expr[1]  or "-" in sub_expr[1] :
                sub_expr[1] = f"\\left({sub_expr[1]}\\right)"
            break
            pass
        sub_expr[1] = Symbol(sub_expr[1])
        return sub_expr
        pass

    pass
#class ArithmeticExpressionSolver:
