'''
Created on 01-Apr-2021
@author: rishi_priyansh
'''
import random
import inspect
import traceback
from sympy import (simplify, sympify, log, symbols, Eq, Matrix, latex, 
                   solve, Rational, diag)


from ..helper import BaseHelper

from xv.km.managers import BaseManager
from xv.km.kelements import KProblemTemplate
        
class PhysicalSystemManager(BaseManager):
    '''
    PhysicalSystemManager
    Example:
        ke = PhysicalSystemManager()
        ke.getRandomProblem()
        ke.getRandomProblem(problem_type = 0)
        ...
        
        ke.printProblem()
        ke.printAnswer()
        ke.printSolution()
        
        ke.printProblemTypes()
        
    '''    
    
    def __new__(cls, *args, **kwargs):
        instance = super(PhysicalSystemManager, cls).__new__(cls, *args, **kwargs)
        for base_class in PhysicalSystemManager.__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_derive_field_of_a_physical_system',
            '_problem_derive_force_of_a_physical_system',
            '_problem_derive_expressions_with_field', 
            '_problem_laplacian_equation_of_potential',
           ])
        pass

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

        problem_s = fr"""
        Derive an expression for field as function of potential and displacment.
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = fr"""

        $\vec{{E}}$ = field
        
        $\vec{{F}}$ = force
        
        $\varphi$ = potenial
        
        $W$ = work
        
        $U$ = energy
        
        $\vec{{r}}$ = displacement
        
        $q$ = property
        
        $\vec{{F}} = q \vec{{E}}$
        
        $d\varphi = \vec{{E}} \cdot \vec{{dr}}$
        
        $dW = \vec{{F}} \cdot \vec{{dr}} = q \vec{{E}} \cdot \vec{{dr}} = q d\varphi$

        $dU + dW = 0$ $\quad\quad$ in a closed system

        $d\varphi = \vec{{E}} \cdot \vec{{dr}}$
        
        $\Rightarrow \frac{{d\varphi}}{{dr}} = \vec{{E}} \cdot \hat{{dr}} $ $\quad \quad$ Dividing both sides by $dr$
        
        $\Rightarrow \frac{{d\varphi}}{{dr}} \cdot \hat{{dr}} = \vec{{E}} \cdot \hat{{dr}} \cdot \hat{{dr}}$ $\quad \quad$ Multipling both sides by $\hat{{dr}}$
        
        $\Rightarrow \frac{{d\varphi}}{{dr}} \cdot \hat{{dr}} = \vec{{E}}$ $\quad \quad$ As $\hat{{dr}} \cdot \hat{{dr}} = 1$
        
        $\Rightarrow \vec{{E}} = \frac{{d\varphi}}{{dr}} \cdot \hat{{dr}}$ $\quad \quad$ Swapping sides
        
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = fr"""
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

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

        problem_s = fr"""
        Derive an expression for force as function of potential and displacment.
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = fr"""

        $\vec{{E}}$ = field
        
        $\vec{{F}}$ = force
        
        $\varphi$ = potenial
        
        $W$ = work
        
        $U$ = energy
        
        $\vec{{r}}$ = displacement
        
        $q$ = property
        
        $\vec{{F}} = q \vec{{E}}$
        $d\varphi = \vec{{E}} \cdot \vec{{dr}}$
        $dW = \vec{{F}} \cdot \vec{{dr}} = q \vec{{E}} \cdot \vec{{dr}} = q d\varphi$
        $dU + dW = 0$ $\quad\quad$ in a closed system

        
        $dW = \vec{{F}} \cdot \vec{{dr}}$
        
        $\Rightarrow \frac{{dW}}{{dr}} = \vec{{F}} \cdot \hat{{dr}} $ $\quad \quad$ Dividing both sides by $dr$
        
        $\Rightarrow \frac{{dW}}{{dr}} \cdot \hat{{dr}} = \vec{{F}} \cdot \hat{{dr}} \cdot \hat{{dr}}$ $\quad \quad$ Multipling both sides by $\hat{{dr}}$
        
        $\Rightarrow \frac{{dW}}{{dr}} \cdot \hat{{dr}} = \vec{{F}}$ $\quad \quad$ As $\hat{{dr}} \cdot \hat{{dr}} = 1$
        
        $\Rightarrow \vec{{F}} = \frac{{dW}}{{dr}} \cdot \hat{{dr}}$ $\quad \quad$ Swapping sides
        
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = fr"""
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

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

        problem_s = fr"""
        Derive expressions as field $\vec{{E}} = k f(q, \vec{{r}})$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = fr"""
        $\vec{{E}}$ = field
        
        $\vec{{F}}$ = force
        
        $\varphi$ = potenial
        
        $W$ = work
        
        $U$ = energy
        
        $\vec{{r}}$ = displacement
        
        $q$ = property
        
        $\vec{{F}} = q \vec{{E}}$ $\quad\quad(1)$
        $d\varphi = \vec{{E}} \cdot \vec{{dr}}$ $\quad\quad(2)$
        $dW = \vec{{F}} \cdot \vec{{dr}} = q \vec{{E}} \cdot \vec{{dr}} = q d\varphi$ $\quad\quad(3)$
        $dU + dW = 0$ $\quad\quad$ in a closed system $\quad\quad(4)$
        
        (1)
        $\vec{{F}} = q \vec{{E}} = q k f(q, \vec{{r}})$

        (2)
        $d\varphi = \vec{{E}} \cdot \vec{{dr}}$
        $\Rightarrow d\varphi = k f(q, \vec{{r}}) \cdot \vec{{dr}}$
        $\Rightarrow \int_{{\varphi_0}}^{{\varphi_1}} d\varphi = \int_{{r_0}}^{{r_1}} k f(q, \vec{{r}}) \cdot \vec{{dr}}$
        
        (3)
        $dW = \vec{{F}} \cdot \vec{{dr}}$
        $\Rightarrow dW = q \vec{{E}} \cdot \vec{{dr}}$
        $\Rightarrow dW = q k f(q, \vec{{r}}) \cdot \vec{{dr}}$
        $\Rightarrow \int_{{W_0}}^{{W_1}} dW = \int_{{r_0}}^{{r_1}} q k f(q, \vec{{r}}) \cdot \vec{{dr}}$
        


        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = fr"""
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate

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

        problem_s = fr"""
        Derive laplacian equation of potential in a electric field
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        
        soln_s = fr"""
        $\vec{{\nabla}}$ = divergence
        $\vec{{E}}$ = field
        $\rho$ = surface charge density
        $\varepsilon_0$ = permittivity
        $\varphi$ = potential
        $\nabla^2$ = laplace operator

        $\vec{{\nabla}} \cdot \vec{{E}} = \frac{{\rho}}{{\varepsilon_0}}$
        
        $\vec{{E}} = -\vec{{\nabla}} \varphi$ $\quad\quad$ From $\vec{{E}} = \frac{{d\varphi}}{{dr}} \hat{{r}}$
        
        $\vec{{\nabla}} \cdot \vec{{E}} = \frac{{\rho}}{{\varepsilon_0}}$
        $\Rightarrow \vec{{\nabla}} \cdot \left ( -\vec{{\nabla}} \varphi \right ) = \frac{{\rho}}{{\varepsilon_0}}$
        $\Rightarrow \nabla^2 \varphi = -\frac{{\rho}}{{\varepsilon_0}}$
        
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        
        answer_s = fr"""
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        
        return problemTemplate

    
