'''
Created on 01-Apr-2021
@author: bthakur

'''

from xv.util import counting_words

import inspect
import traceback

import random
from xv.km.util import latex_fraction

from xv.util import toIntOrFloat

from sympy import (symbols, Symbol, Function, Rational,
                   latex, Eq, Matrix, latex, sympify, sqrt,
                   UnevaluatedExpr, atan
                   )
import numpy as np
import random


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

from xv.util import toIntOrFloat

# _complex_number_manager
# ComplexNumberManager
        
class ComplexNumberManager(BaseManager):
        
    '''
    Complex Numbers


    Minimum Grade: 3
    Maximum Grade: 7


    Examples
    --------
    ke = ComplexNumberManager()
    ke 
    
    ke.printProblemTypes()
    ke.helpProblemType(0)
    
    ke.getRandomProblem()
    ke.getRandomProblem(problem_type = 0)


    ke.printProblem()
    ke.printAnswer()
    ke.printSolution()


    doc_style: xv_doc
    ''' 

    
    def __new__(cls, *args, **kwargs):
        instance = super(ComplexNumberManager, cls).__new__(cls, *args, **kwargs)
        for base_class in ComplexNumberManager.__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_imaginary_number',
                '_problem_complex_number',
                '_problem_complex_number_operations',
                '_problem_nth_root',
                '_problem_challenging_complex_number_quesions',
            ]
        )
        pass
    
    def _problem_imaginary_number(self, *args, **kwargs):
        """

        Minimum Grade: 5
        Maximum Grade: 12

        doc_style: xv_doc
        """

        cn_helper = self.base_helper.get_algebra_helper().get_complex_number_helper()
        '''
        circle_helper = self.geometry_helper.get_circle_helper()
        plot_code, svg_str = circle_helper.plot_a_unit_circle_with_marked_integers(point_count,
                                                            use_cache = True)
        '''
        n = cn_helper.get_random_negative_number()
        
        imaginary_root_solution = cn_helper.get_imaginary_root_solution(n)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        
        prob_s = f"""
        What is square root of $\\displaystyle {latex(n)}$?
        """
        problemTemplate.add_problem(prob_s.strip(), "text/html")
        
        soln_s = f"""
        {imaginary_root_solution}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        $\\displaystyle {latex(sqrt(n))}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        return problemTemplate
        pass
   
    def _problem_complex_number(self, *args, **kwargs):
        """

        Minimum Grade: 5
        Maximum Grade: 12

        doc_style: xv_doc
        """

        cn_helper = self.base_helper.get_algebra_helper().get_complex_number_helper()
        result = cn_helper.get_complex_number_properties()
        
        z_std = result['z_std']
        z = result['z']
        
        self.z = z
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        prob_s = f"""
        Write the following properties of complex number $\\displaystyle {z}$:
        
        {result['z_props_keys_str']}
        """
        problemTemplate.add_problem(prob_s.strip(), "text/html")

        
        soln_s = f"""
        The standard form of a complex number is $\\displaystyle 
        {latex(z_std.Re)} + i{latex(z_std.Im)}$.
        So, we can say, for $\\displaystyle {z}$:
        $\\displaystyle {latex(z_std.Re)} = {latex(z.Re)}$
        $\\displaystyle {latex(z_std.Im)} = {latex(z.Im)}$
        
        {result['z_props_str']}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['z_props_str']}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        return problemTemplate
        pass
   

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

        Minimum Grade: 5
        Maximum Grade: 12

        doc_style: xv_doc
        """

        cn_helper = self.base_helper.get_algebra_helper().get_complex_number_helper()
        z1 = cn_helper.get_random_complex_number()
        z2 = cn_helper.get_random_complex_number()
        n = random.randint(-9, 9)
        while n == 0:
            n = random.randint(-9, 9)
        result = cn_helper.get_complex_number_operations(z1, z2, n)
        self.z1 = z1
        self.z2 = z2
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        prob_s = f"""
        Write the following properties of complex number:
        
        {result['z_props_keys_str']}
        """
        problemTemplate.add_problem(prob_s.strip(), "text/html")

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

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

        Minimum Grade: 5
        Maximum Grade: 12

        doc_style: xv_doc
        """

        cn_helper = self.base_helper.get_algebra_helper().get_complex_number_helper()

        x, y, n = [0, 0, 0]
        while (x == 0 and y == 0) or n == 0:
            x = random.randint(-9, 9)
            y = random.randint(-9, 9)
            n = random.randint(-9, 9)
        
        #x = -1 
        #y = 0
        #n = 3
        z = ComplexNumber(x, y)
            
        result = cn_helper.get_nth_root(z, n)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        prob_s = f"""
        Find ${n}$th root of ${z}$:
        """
        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"""
        $\\displaystyle {latex(result['answer'])}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        return problemTemplate
        pass
   


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

        Minimum Grade: 5
        Maximum Grade: 12

        doc_style: xv_doc
        """

        cn_helper = self.base_helper.get_algebra_helper().get_complex_number_helper()

        result = cn_helper.get_problem_challenging_complex_number_quesions(**kwargs)
        
        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
   
