'''
Created on 16-Apr-2021

@author: bthakur

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

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



from xv.util import number_to_nth

'''

import inspect
import traceback

import random
from xv.km.util import latex_fraction

from xv.util import toIntOrFloat

from sympy import (symbols, Symbol, Function,
                   latex)

from ...helper import BaseHelper, CalculusHelper
from xv.km.managers import BaseManager
from xv.km.kelements import KProblemTemplate
        
# _differentiation_basics_manager
# DifferentiationBasicsManager
  
class DifferentiationBasicsManager(BaseManager):
    '''
    Basic Differentiation Rules
    Example:
        ke = DifferentiationBasicsManager()
        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(DifferentiationBasicsManager, cls).__new__(cls, *args, **kwargs)
        for base_class in DifferentiationBasicsManager.__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_calculate_rate',
                '_problem_calculate_cost',
                '_problem_calculate_cost_from_cost',
                '_problem_calculate_cost_from_rate_slope',
                '_problem_calculate_rate_slopes',
                '_problem_write_rules_for_cost',
                '_problem_plot_qty_cost',
             ])
        pass

    def _problem_calculate_rate(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        dbh = self.base_helper.get_calculus_helper().get_differentiation_basics_helper()
        data = dbh.problem_calculate_rate()
        
        problemTemplate.add_problem(data['prob_s'], 'text/html')
        problemTemplate.add_solution(data['soln_s'], 'text/html')
        problemTemplate.add_answer(data['answer_s'], 'text/html')
        
        return problemTemplate
        pass
        
    def _problem_calculate_cost(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        dbh = self.base_helper.get_calculus_helper().get_differentiation_basics_helper()
        data = dbh.problem_calculate_cost()
        
        problemTemplate.add_problem(data['prob_s'], 'text/html')
        problemTemplate.add_solution(data['soln_s'], 'text/html')
        problemTemplate.add_answer(data['answer_s'], 'text/html')
        
        return problemTemplate
        pass
        
    def _problem_calculate_cost_from_cost(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        dbh = self.base_helper.get_calculus_helper().get_differentiation_basics_helper()
        data = dbh.problem_calculate_cost_from_cost()
        
        problemTemplate.add_problem(data['prob_s'], 'text/html')
        problemTemplate.add_solution(data['soln_s'], 'text/html')
        problemTemplate.add_answer(data['answer_s'], 'text/html')
        
        return problemTemplate
        pass


    def _problem_calculate_cost_from_rate_slope(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        dbh = self.base_helper.get_calculus_helper().get_differentiation_basics_helper()
        data = dbh.problem_calculate_cost_from_rate_slope()
        
        prob_s = f"""
        Find the cost of {data['qty']} {data['item_names']} if the cost table is as follows:
        {data['df_html']}
        """
        
        problemTemplate.add_problem(prob_s, 'text/html')
        problemTemplate.add_solution(data['soln_s'], 'text/html')
        problemTemplate.add_answer(data['answer_s'], 'text/html')
        
        return problemTemplate
        pass


    def _problem_calculate_rate_slopes(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        dbh = self.base_helper.get_calculus_helper().get_differentiation_basics_helper()
        data = dbh.problem_calculate_cost_from_rate_slope(df_with_rates = True)
        
        prob_s = f"""
        Write modified cost table and find the cost of {data['qty']} {data['item_names']} if the cost table is as follows:
        {data['df_html']}
        """
        
        problemTemplate.add_problem(prob_s, 'text/html')
        problemTemplate.add_solution(data['soln_s'], 'text/html')
        problemTemplate.add_answer(data['answer_s'], 'text/html')
        
        return problemTemplate
        pass

    def _problem_write_rules_for_cost(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        dbh = self.base_helper.get_calculus_helper().get_differentiation_basics_helper()
        data = dbh.problem_calculate_cost_from_rate_slope(df_with_rates = True,
                                                          rules = True)
        
        prob_s = f"""
        Write cost function and find the cost of {data['qty']} {data['item_names']} if the cost table is as follows:
        {data['df_html']}
        """
        
        problemTemplate.add_problem(prob_s, 'text/html')
        problemTemplate.add_solution(data['soln_s'], 'text/html')
        problemTemplate.add_answer(data['answer_s'], 'text/html')
        
        return problemTemplate
        pass


    def _problem_plot_qty_cost(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        dbh = self.base_helper.get_calculus_helper().get_differentiation_basics_helper()
        data = dbh.problem_calculate_cost_from_rate_slope(df_with_rates = True,
                                                          rules = True,
                                                          plot_rules = True)
        
        prob_s = f"""
        Plot cost function and find the cost of {data['qty']} {data['item_names']} if the cost table is as follows:
        {data['df_html']}
        """
        
        problemTemplate.add_problem(prob_s, 'text/html')
        problemTemplate.add_solution(data['soln_s'], 'text/html')
        problemTemplate.add_answer(data['answer_s'], 'text/html')

        problemTemplate.add_solution(data['svg_str'], 'text/svg')
        problemTemplate.add_answer(data['svg_str'], 'text/svg')
        
        return problemTemplate
        pass
                
    