'''
Created on 02-Mar-2021

@author: bthakur
'''

'''
Created on 07-Feb-2021

https://math.meta.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference

@author: bthakur
'''
import os 
import decimal
import numpy as np
import random
import inspect
import traceback
from sympy import (simplify, sympify, 
                   log, exp,
                   symbols, Eq, Matrix, Function,
                   latex, 
                   solve, Rational, diag,
                   Derivative, Integral,
                   oo, pi, E,
                   sin, cos, tan)
        
from ...helper import BaseHelper
from ...helper import CalculusHelper

from xv.km.managers import BaseManager
from xv.km.kelements import KProblemTemplate, KPrintElement

# _max_min_manager
# MaxMinManager
        
class MaxMinManager(BaseManager):
    '''
    Calculating min and max - with Calculus
    Example:
        ke = MaxMinManager()
        ke
        
        ke.printProblemTypes()
        
        ke.getRandomProblem()
        ke.getRandomProblem(problem_type = 0)
        ke.getRandomProblem(problem_type = 1)
        ...
        
        ke.printProblem()
        ke.printAnswer()
        ke.printSolution()
        
        ke.printLength(2, 5, 3, -1)
        ke.printMovementLengths()        
        
        
    '''    
    def __new__(cls, *args, **kwargs):
        instance = super(MaxMinManager, cls).__new__(cls, *args, **kwargs)
        for base_class in MaxMinManager.__bases__:
            base_class.__init__(instance, *args, **kwargs)
        return instance
    
    def __init__(self, *args, **kwargs):
        self.base_helper = BaseHelper(**kwargs)
        self.calculus_helper = self.base_helper.get_calculus_helper()
        #self.calculus_helper = CalculusHelper(**kwargs)
        
        pass


    def _init_problem_types(self, *args, **kwargs):
        self._append_problem_types([
                '_problem_find_max_min_single_variabale',
                '_problem_applied_max_min',
                '_problem_max_min_manager',
             ])
        pass

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

        mmh = self.base_helper.get_calculus_helper().get_max_min_helper()
        
        x = symbols('x')
        expr = kwargs.get('expr', None)
        
        if not expr is None:
            expr = sympify(expr)
            x = list(expr.free_symbols)[0]
            pass
        else:
            expr = mmh.get_random_expr(x)
            pass
        
        self._expr = expr
        self._x = x
        
        result = mmh.get_extrema_solution(expr, x)
        
        statement = f"""
        find max value of $\\displaystyle f({latex(x)}) = {latex(expr)}$
        """
        problemTemplate.add_problem(statement)
        
        soln_s = result['soln_s']
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        if result['max_values_str']:
            answer_s = f"""
            <b>Minimum Values:</b>
            
            {result['max_values_str']}
            """
            problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        if result['min_values_str']:
            answer_s = f"""
            <b>Minimum Values:</b>
            
            {result['min_values_str']}
            """
            problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        
        return problemTemplate
        pass
    

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

        mmh = self.base_helper.get_calculus_helper().get_max_min_helper()
        
        
        result = mmh.get_random_applied_problem()
        expr = result['expr']
        x = result['x']
        
        if result['problem_s']:
            problemTemplate.add_problem(result['problem_s'], 'text/html')
        
        if result['pre_solution']:
            problemTemplate.add_solution(result['pre_solution'], 'text/html')
        
        if result['soln_s']:
            problemTemplate.add_solution(result['soln_s'], 'text/html')
        
        if result['post_solution']:
            problemTemplate.add_solution(result['post_solution'], 'text/html')
        
        
        if result['max_values_str']:
            answer_s = f"""
            <b>Minimum Values:</b>
            
            {result['max_values_str']}
            """
            problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        if result['min_values_str']:
            answer_s = f"""
            <b>Minimum Values:</b>
            
            {result['min_values_str']}
            """
            problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        
        return problemTemplate
        pass
    
    
