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

from sympy import ( Eq,
                    Limit,
                    Pow, Mul, Add, exp,
                    Function, latex, Integral, solve, 
                    UnevaluatedExpr, S, oo, log, logcombine)


import numpy as np
import random
import inspect
import traceback
from sympy import (symbols, Symbol)

from xv.km.util import latex_fraction, latex_atom
from ..helper import BaseHelper

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

# _optics_manager
# OpticsManager
        
class OpticsManager(BaseManager):
    '''
    Optics Fundamentals
    Example:
        ke = OpticsManager()
        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(OpticsManager, cls).__new__(cls, *args, **kwargs)
        for base_class in OpticsManager.__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_refractive_index',
            '_problem_mirror_radius_focal_length',
            '_problem_lens_radius_focal_length',
            '_problem_magnification_by_mirror',
            '_problem_magnification_by_a_series_of_mirrors',
            
            '_problem_magnification_by_lens',
            '_problem_magnification_by_a_series_of_lenses',

            
            '_problem_relative_refractive_index',
            '_problem_mirror_formula',
            '_problem_lens_formula',
            '_problem_snells_law',
            
            '_problem_iit_geometrical_optics',
            '_problem_iit_wave_optics',
            
            ])
        pass


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

        optics_helper = self.base_helper.get_optics_helper()

        result = optics_helper.get_problem_refractive_index(**kwargs)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

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

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

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

        return problemTemplate
        pass

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

        optics_helper = self.base_helper.get_optics_helper()

        result = optics_helper.get_problem_mirror_radius_focal_length(**kwargs)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

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

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

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

        return problemTemplate
        pass

    def _problem_lens_radius_focal_length(self, *args, **kwargs):
        """
        """
        
        optics_helper = self.base_helper.get_optics_helper()
        
        result = optics_helper.get_problem_lens_radius_focal_length(**kwargs)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        prob_s = f"""
        {result['prob_s'].strip()}
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')
        
        soln_s = f"""
        {result['soln_s'].strip()}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s'].strip()}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    def _problem_magnification_by_mirror(self, *args, **kwargs):
        """
        """
        
        optics_helper = self.base_helper.get_optics_helper()
        
        result = optics_helper.get_problem_magnification_by_mirror(**kwargs)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        prob_s = f"""
        {result['prob_s'].strip()}
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')
        
        soln_s = f"""
        {result['soln_s'].strip()}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s'].strip()}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass


    def _problem_magnification_by_a_series_of_mirrors(self, *args, **kwargs):
        """
        """
        
        optics_helper = self.base_helper.get_optics_helper()
        
        result = optics_helper.get_problem_magnification_by_a_series_of_mirrors(**kwargs)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        prob_s = f"""
        {result['prob_s'].strip()}
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')
        
        soln_s = f"""
        {result['soln_s'].strip()}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s'].strip()}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    def _problem_magnification_by_lens(self, *args, **kwargs):
        """
        """
        
        optics_helper = self.base_helper.get_optics_helper()
        
        result = optics_helper.get_problem_magnification_by_lens(**kwargs)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        prob_s = f"""
        {result['prob_s'].strip()}
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')
        
        soln_s = f"""
        {result['soln_s'].strip()}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s'].strip()}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    def _problem_magnification_by_a_series_of_lenses(self, *args, **kwargs):
        """
        """
        
        optics_helper = self.base_helper.get_optics_helper()
        
        result = optics_helper.get_problem_magnification_by_a_series_of_lenses(**kwargs)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        prob_s = f"""
        {result['prob_s'].strip()}
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')
        
        soln_s = f"""
        {result['soln_s'].strip()}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s'].strip()}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    def _problem_relative_refractive_index(self, *args, **kwargs):
        """
        """
        
        optics_helper = self.base_helper.get_optics_helper()
        
        result = optics_helper.get_problem_relative_refractive_index(**kwargs)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        prob_s = f"""
        {result['prob_s'].strip()}
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')
        
        soln_s = f"""
        {result['soln_s'].strip()}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s'].strip()}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass


    def _problem_mirror_formula(self, *args, **kwargs):
        """
        """
        
        optics_helper = self.base_helper.get_optics_helper()
        
        result = optics_helper.get_problem_mirror_formula(**kwargs)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        prob_s = f"""
        {result['prob_s'].strip()}
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')
        
        soln_s = f"""
        {result['soln_s'].strip()}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s'].strip()}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    def _problem_lens_formula(self, *args, **kwargs):
        """
        """
        
        optics_helper = self.base_helper.get_optics_helper()
        
        result = optics_helper.get_problem_lens_formula(**kwargs)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        prob_s = f"""
        {result['prob_s'].strip()}
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')
        
        soln_s = f"""
        {result['soln_s'].strip()}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s'].strip()}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass

    def _problem_snells_law(self, *args, **kwargs):
        """
        """
        
        optics_helper = self.base_helper.get_optics_helper()
        
        result = optics_helper.get_problem_snells_law(**kwargs)
        
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')
        
        prob_s = f"""
        {result['prob_s'].strip()}
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')
        
        soln_s = f"""
        {result['soln_s'].strip()}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = f"""
        {result['answer_s'].strip()}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate
        pass
    
    def _problem_iit_geometrical_optics(self, *args, **kwargs):
        """
        """
        
        folder_path = "question_bank/physics/optics"
        search_file_paths = [
            "iit_geometrical_optics.txt"
            ]
        
        file_paths = self.get_q_bank_factory().search_question_bank_files(folder_path, search_file_paths)
        return self.get_q_bank_factory().PROBLEM_TEMPLATE_Q_BANK_RANDOM_QUESTION(file_paths, *args, **kwargs)


    def _problem_iit_wave_optics(self, *args, **kwargs):
        """
        """
        
        folder_path = "question_bank/physics/optics"
        search_file_paths = [
            "iit_wave_optics.txt"
            ]
        
        file_paths = self.get_q_bank_factory().search_question_bank_files(folder_path, search_file_paths)
        return self.get_q_bank_factory().PROBLEM_TEMPLATE_Q_BANK_RANDOM_QUESTION(file_paths, *args, **kwargs)


