'''
Created on 16-Apr-2021

@author: bthakur
'''
import os 
import numpy as np
import random
import inspect
import traceback

import sympy

from sympy import ( latex,symbols, diff, Symbol, Mul, Matrix, Function,
                    factorial, sympify, Rational, log,
                    Derivative, factor, Eq, simplify, expand,
                    exp, sin, cos, cosh, sinh, pi, sqrt, atan, Limit,
                    expand_trig, trigsimp, srepr, Integer, Pow, Add)

from sympy import UnevaluatedExpr as ueval

from sympy.core.numbers import One, Integer
from sympy.simplify.fu import TR1, TR2, TR2i, fu, TR16, TR22


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

# _standard_integration_manager
# StandardIntegrationManager
        
class StandardIntegrationManager(BaseManager):
    '''
    Integration 
    Example:
        ke = StandardIntegrationManager()
        ke
        
        ke.printProblemTypes()
        
        ke.getRandomProblem()
        ke.getRandomProblem(problem_type = 0)
        ke.getRandomProblem(problem_type = 1)
        ...
        
        ke.printProblem()
        ke.printAnswer()
        ke.printSolution()
        
        
    '''    
    def __new__(cls, *args, **kwargs):
        instance = super(StandardIntegrationManager, cls).__new__(cls, *args, **kwargs)
        for base_class in StandardIntegrationManager.__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_standrad_integral',
            '_problem_standrad_integral_by_reversal',
            '_problem_standrad_integral_by_substitution',
            '_problem_standrad_integration_by_parts',
            '_problem_standrad_integration_by_parts_in_chain',
             ])
        pass
    
    def _problem_standrad_integral(self, *args, **kwargs):
        
        index = kwargs.get('index', None)
        
        intgr_helper = self.base_helper.get_calculus_helper().get_std_integration_helper()
        result = intgr_helper.get_standrad_integral(index = index)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        
        prob_s = f"""
        {result['prob_s']}
        """
        
        problemTemplate.add_problem(prob_s.strip(), 'text/html')


        soln_s = f"""
        {result['soln_s']}
        """
        
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s']}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate

        pass

    def _problem_standrad_integral_by_reversal(self, *args, **kwargs):
        
        index = kwargs.get('index', None)
        
        intgr_helper = self.base_helper.get_calculus_helper().get_std_integration_helper()
        result = intgr_helper.get_standrad_integral_by_reversal(index = index)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        
        prob_s = f"""
        {result['prob_s']}
        """
        
        problemTemplate.add_problem(prob_s.strip(), 'text/html')


        soln_s = f"""
        {result['soln_s']}
        """
        
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s']}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate

        pass

    def _problem_standrad_integral_by_substitution(self, *args, **kwargs):
        
        index = kwargs.get('index', None)
        
        intgr_helper = self.base_helper.get_calculus_helper().get_std_integration_helper()
        result = intgr_helper.get_standrad_integral_by_substitution(index = index)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        
        prob_s = f"""
        {result['prob_s']}
        """
        
        problemTemplate.add_problem(prob_s.strip(), 'text/html')


        soln_s = f"""
        {result['soln_s']}
        """
        
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s']}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate

        pass

    def _problem_standrad_integration_by_parts(self, *args, **kwargs):
        
        index = kwargs.get('index', None)
        
        intgr_helper = self.base_helper.get_calculus_helper().get_std_integration_helper()
        result = intgr_helper.get_standrad_integration_by_parts(index = index)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        
        prob_s = f"""
        {result['prob_s']}
        """
        
        problemTemplate.add_problem(prob_s.strip(), 'text/html')


        soln_s = f"""
        {result['soln_s']}
        """
        
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s']}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate

        pass


    def _problem_standrad_integration_by_parts_in_chain(self, *args, **kwargs):
        
        index = kwargs.get('index', None)
        
        intgr_helper = self.base_helper.get_calculus_helper().get_std_integration_helper()
        result = intgr_helper.get_standrad_integration_by_parts_in_chain(index = index)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        
        prob_s = f"""
        {result['prob_s']}
        """
        
        problemTemplate.add_problem(prob_s.strip(), 'text/html')


        soln_s = f"""
        {result['soln_s']}
        """
        
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s']}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate

        pass

