'''
Created on 16-Apr-2021

@author: bthakur
'''
import os 
import random
import inspect
import traceback

import sympy
import numpy as np

from sympy import (symbols, Function, Derivative, diff,
                   simplify, latex,
                   Symbol, Sum, binomial, factorial, UnevaluatedExpr
                   )
from ...util import MathUtil
from xv.util import list_to_str
        

from xv.km.kelements import KPrintElement

from xv.km.util import latex_fraction


from ...helper import BaseHelper
from xv.km.managers import BaseManager
from xv.km.kelements import KProblemTemplate

# _multinomial_manager
# MultinomialManager
        
class MultinomialManager(BaseManager):
    '''
    This class deals with expressions of more than two variable and their applications.
    For two variables, see BinomialManager

    Examples
    --------

    from xv.math.calculus.differentiation import MultinomialManager
    ke = MultinomialManager()
    ke
    
    ke.printProblemTypes()
    
    ke.getRandomProblem()
    ke.getRandomProblem(problem_type = 0)
    ke.getRandomProblem(problem_type = 1)
    ...
    
    ke.printProblem()
    ke.printAnswer()
    ke.printSolution()
    

    doc_style: xv_doc
    ''' 

    def __new__(cls, *args, **kwargs):
        instance = super(MultinomialManager, cls).__new__(cls, *args, **kwargs)
        for base_class in MultinomialManager.__bases__:
            base_class.__init__(instance, *args, **kwargs)
        return instance
    
    def __init__(self, *args, **kwargs):
        self.base_helper = BaseHelper(**kwargs)
        pass


    def _init_problem_types(self, *args, **kwargs):
        self._append_problem_types([
                '_problem_multinomial_term',
                '_problem_multinomial_expansion',
             ])
        pass

    def _problem_multinomial_term(self, *args, **kwargs):
        """

        Minimum Grade: 6
        Maximum Grade: 12
        doc_style: xv_doc
        """
        
        multinomial_helper = self.base_helper.get_algebra_helper().get_multinomial_helper()
        
        result = multinomial_helper.get_multinomial_term()
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        
        problem_s = f"""
        Find the term with variable expression $\\displaystyle 
        {latex(result['var_expr'])}$ in $\\displaystyle 
        {latex(result['multinomial_expr'])}$.
        """
        problemTemplate.add_problem(problem_s, 'text/html')


        soln_s = f"""
        Term with variable expression $\\displaystyle 
        {latex(result['var_expr'])}$ in $\\displaystyle 
        {latex(result['multinomial_expr'])}$
        
        $\\displaystyle 
        = {latex(result['ueval_term'])}$
        
        
        $\\displaystyle 
        = {latex(result['expanded_term'])}$
        
        
        $\\displaystyle 
        = {latex(result['term'])}$
        
        
        """

        
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        $\\displaystyle 
        {latex(result['term'])}$
        
        """

        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        
        return problemTemplate
        pass

    def _problem_multinomial_expansion(self, *args, **kwargs):
        """

        Minimum Grade: 6
        Maximum Grade: 12
        doc_style: xv_doc
        """
        count = kwargs.get('count', None)
        if count is None:
            count = random.randint(2, 4)
        
        multinomial_helper = self.base_helper.get_algebra_helper().get_multinomial_helper()
        
        m_vars = multinomial_helper.get_default_vars(count = count)
        
        result = multinomial_helper.get_multinomial_expansion(m_vars)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        
        problem_s = f"""
        Expand the series $\\displaystyle 
        {latex(result['multinomial_expr'])}$.
        """
        problemTemplate.add_problem(problem_s, 'text/html')


        soln_s = f"""
        $\\displaystyle {latex(result['multinomial_expr'])}$
        
        $\\displaystyle = {latex(result['ueval_expansion'])}$
        
        $\\displaystyle = {latex(result['expansion'])}$
        
        $\\displaystyle = {latex(result['simplified'])}$
        
        """

        
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        $\\displaystyle {latex(result['simplified'])}$
        """

        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        
        return problemTemplate
        pass


    pass