'''
Created on 26-Jan-2022
@author: bthakur
'''
import random
import inspect
import traceback
from sympy import latex

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


# _fast_arithmetic_manager
# FastArithmeticManager
        
class FastArithmeticManager(BaseManager):
    '''
    Example:
        ke = FastArithmeticManager()
        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(FastArithmeticManager, cls).__new__(cls, *args, **kwargs)
        for base_class in FastArithmeticManager.__bases__:
            base_class.__init__(instance, *args, **kwargs)
        return instance
    
    def __init__(self, *args, **kwargs):
        self.base_helper = BaseHelper(**kwargs)
        pass


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

        helper = self.base_helper.get_arithmetic_helper().get_fast_arithmetic_helper()
        
        result = helper.get_random_problem(ten_exp = ten_exp, **kwargs)
        
        statement = f"""
        {result['statement']}
        """
        problemTemplate.add_problem(statement, "text/html")

        if result.get('soln_statement', None):
            soln_s = result['soln_statement']
        else:
            soln_s = f"""
            $\\displaystyle {result['expr_latex']}$
            
            $\\displaystyle = {latex(result['answer'])}$
            """
            pass
        
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        $\\displaystyle {latex(result['answer'])}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

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

        helper = self.base_helper.get_arithmetic_helper().get_fast_arithmetic_helper()
        
        result = helper.get_random_problems(ten_exp = ten_exp, **kwargs)
        
        statement = f"""
        {result['statements']}
        """
        problemTemplate.add_problem(statement, "text/html")

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

        answer_s = f"""
        {result['answers']}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass
        
    
    def _init_problem_types(self, *args, **kwargs):
        self._append_problem_types([
                '_problem_single_digit',
                '_problem_single_digit_multiple',
                '_problem_tens',
                '_problem_tens_multiple',
                '_problem_hundreds',
                '_problem_hundreds_multiple',
                '_problem_mixed',
                '_problem_mixed_multiple',
                '_problem_advanced',
                '_problem_advanced_multiple',
                
             ])
        pass
    
    def _problem_single_digit(self, *args, **kwargs):
        ten_exp = 0
        return self._TEMPLATE_SINGLE_PROBLEM(ten_exp, *args, **kwargs)
        pass

    def _problem_single_digit_multiple(self, *args, **kwargs):
        ten_exp = 0
        return self._TEMPLATE_MULTIPLE_PROBLEM(ten_exp, *args, **kwargs)
        pass
        
    def _problem_tens(self, *args, **kwargs):
        ten_exp = 1
        return self._TEMPLATE_SINGLE_PROBLEM(ten_exp, *args, **kwargs)
        pass
        pass

    def _problem_tens_multiple(self, *args, **kwargs):
        ten_exp = 1
        return self._TEMPLATE_MULTIPLE_PROBLEM(ten_exp, *args, **kwargs)
        pass
        
    def _problem_hundreds(self, *args, **kwargs):
        ten_exp = 2
        return self._TEMPLATE_SINGLE_PROBLEM(ten_exp, *args, **kwargs)
        pass

    def _problem_hundreds_multiple(self, *args, **kwargs):
        ten_exp = 2
        return self._TEMPLATE_MULTIPLE_PROBLEM(ten_exp, *args, **kwargs)
        pass
    
    def _problem_mixed(self, *args, **kwargs):
        ten_exp = 3
        kwargs['mixed'] = True
        return self._TEMPLATE_SINGLE_PROBLEM(ten_exp, *args, **kwargs)
        pass

    def _problem_mixed_multiple(self, *args, **kwargs):
        ten_exp = 3
        kwargs['mixed'] = True
        return self._TEMPLATE_MULTIPLE_PROBLEM(ten_exp, *args, **kwargs)
        pass    
    
    def _problem_advanced(self, *args, **kwargs):
        ten_exp = 3
        kwargs['mixed'] = True
        kwargs['advanced'] = True
        return self._TEMPLATE_SINGLE_PROBLEM(ten_exp, *args, **kwargs)
        pass

    def _problem_advanced_multiple(self, *args, **kwargs):
        ten_exp = 3
        kwargs['mixed'] = True
        kwargs['advanced'] = True
        return self._TEMPLATE_MULTIPLE_PROBLEM(ten_exp, *args, **kwargs)
        pass    
    
    