'''
Created on 12-Jul-2021

@author: rishi_priyansh
'''
import inspect
import traceback
import random

from sympy import (Symbol, symbols, Function, latex, Eq,
                   pi,
                   UnevaluatedExpr,
                   Integral,
                   sin, cos, pi, atan
                   )

from sympy import (pi, latex,
                   Rational, 
                   symbols, Symbol, Function, 
                   UnevaluatedExpr,
                   Eq, dsolve, solve,
                   sqrt)
import sympy


from xv.km.util import PintUnitSystem

from xv.km.ui import SvgHelper         

from xv.km.helper import BaseEquationHelper


class LightMechanicsHelper:
    def __init__(self, b = None, e = None, count = 2, **kwargs):
        self.verbose = kwargs.get('verbose', False)
        pass

    def get_relation(self, 
                     method_name,
                     as_strings = False,
                     sep = "\n\n"):
        
        data_method = getattr(self, method_name)
        
        be_helper = BaseEquationHelper(verbose = self.verbose)
        relation_data = be_helper.get_relation(data_method)
        result = be_helper.get_standard_relation_statements(relation_data,
                                                            as_strings = as_strings,
                                                            sep = sep)
        return result
        
    def get_computation(self, 
                     method_name,
                     as_strings = False,
                     sep = "\n\n"):
        
        data_method = getattr(self, method_name)
        
        be_helper = BaseEquationHelper(verbose = self.verbose)
        relation_data = be_helper.get_computation(data_method)
        result = be_helper.get_standard_relation_statements(relation_data,
                                                            as_strings = as_strings,
                                                            sep = sep)
        return result
        
    def get_proportional_computation(self, 
                     method_name,
                     as_strings = False,
                     sep = "\n\n"):
        
        data_method = getattr(self, method_name)
        
        be_helper = BaseEquationHelper(verbose = self.verbose)
        relation_data = be_helper.get_computation(data_method)
        result = be_helper.get_standard_proportional_computation_statements(relation_data,
                                                            as_strings = as_strings,
                                                            sep = sep)
        return result

    def get_polarization(self):

        theta_B, n_1, n_2 = symbols(r'theta_B, n_1, n_2')
        
        label_dict = {
            theta_B: "Brewster's angle",
            n_1: "Refractive index of the incident medium",
            n_2: "refractive index of the reflecting medium",
        }

        ps = PintUnitSystem()
        n_1_val = random.randint(1, 400)*10**-2
        n_2_val = random.randint(1, 400)*10**-2
        theta_B_val = float(atan(n_1_val/n_2_val).n())

        var_values = {
            n_1: n_1_val,
            n_2: n_1_val,
            theta_B: theta_B_val,
        }


        lhs_symbol = theta_B
        const_symbols = []
        rhs_symbols = [n_1, n_2]

        t_lhs = atan(theta_B)
        t_const = 1
        t_rhs = n_1/n_2
                                  
        eq = Eq(t_lhs, t_rhs)
                  
        data = {
            'prop_symbols': [lhs_symbol, const_symbols, rhs_symbols],
            'label_dict': label_dict,
            'var_values': var_values,
            'constant_value': t_const,
            'eq': eq,
            }

        return data
        pass

    def get_mirror_formula_2(self):

        #f, h_i, h_O, d_i, d_O = symbols(r'f, h_i, h_O, d_i, d_O')
        f, h_i, h_O, d_i, d_O = symbols(r"f, h, h^', v, u")
        
        label_dict = {
            d_O: "Distance of object from mirror",
            d_i: "Distance of image from mirror",
            h_i: "Image height",
            h_O: "Object height",
        }

        ps = PintUnitSystem()
        d_O_val = random.randint(1, 100)*10**-2
        d_i_val = random.randint(1, 100)*10**-2
        h_O_val = random.randint(1, 100)*10**-2
        h_i_val = (d_i_val/d_O_val)*h_O_val

        var_values = {
            d_O: d_O_val * ps.convert_to_base_units('meter'),
            d_i: d_i_val * ps.convert_to_base_units('meter'),
            h_O: h_O_val * ps.convert_to_base_units('meter'),
            h_i: h_i_val * ps.convert_to_base_units('meter'),
        }


        lhs_symbol = h_i
        const_symbols = []
        rhs_symbols = [d_i, d_O, h_O]

        t_lhs = h_i
        t_const = 1
        t_rhs = (d_i/d_O)*UnevaluatedExpr(h_O)
                                  
        eq = Eq(t_lhs, t_rhs)
                  
        data = {
            'prop_symbols': [lhs_symbol, const_symbols, rhs_symbols],
            'label_dict': label_dict,
            'var_values': var_values,
            'constant_value': t_const,
            'eq': eq,
            }

        return data
        pass

    def get_mirror_formula_1(self):

        #f, h_i, h_O, d_i, d_O = symbols(r'f, h_i, h_O, d_i, d_O')
        f, h_i, h_O, d_i, d_O = symbols(r"f, h, h^', v, u")
        
        label_dict = {
            f: "Focal length of mirror",
            d_O: "Distance of object from mirror",
            d_i: "Distance of image from mirror",
        }

        ps = PintUnitSystem()
        d_O_val = random.randint(1, 100)*10**-2
        d_i_val = random.randint(1, 100)*10**-2
        f_val = ((1/d_O_val) + (1/d_i_val))**-1
        var_values = {
            f: f_val * ps.convert_to_base_units('meter'),
            d_O: d_O_val * ps.convert_to_base_units('meter'),
            d_i: d_i_val * ps.convert_to_base_units('meter'),
        }


        lhs_symbol = f
        const_symbols = []
        rhs_symbols = [d_i, d_O]

        t_lhs = 1/f
        t_const = 1
        t_rhs = ((1/d_O) + (1/d_i))
                                  
        eq = Eq(t_lhs, t_rhs)
                  
        data = {
            'prop_symbols': [lhs_symbol, const_symbols, rhs_symbols],
            'label_dict': label_dict,
            'var_values': var_values,
            'constant_value': t_const,
            'eq': eq,
            }

        return data
        pass

    def get_lens_equation_2(self):

        T, f = symbols(r'T, f')

        label_dict = {
            f: "Frequency",
            T: "Time period",
        }

        ps = PintUnitSystem()
        T_val = random.randint(1, 60)
        f_val = 1/T_val
        
        var_values = {
            f: f_val * ps.convert_to_base_units('1/sec'),
            T: T_val * ps.convert_to_base_units('sec'),
        }


        lhs_symbol = f
        const_symbols = []
        rhs_symbols = [T]

        t_lhs = f
        t_const = 1
        t_rhs = 1/T
                                  
        eq = Eq(t_lhs, t_rhs)
                  
        data = {
            'prop_symbols': [lhs_symbol, const_symbols, rhs_symbols],
            'label_dict': label_dict,
            'var_values': var_values,
            'constant_value': t_const,
            'eq': eq,
            }

        return data
        pass

    def get_lens_equation_1(self):

        m, h_i, h_O, d_i, d_O = symbols(r'm, h_i, h_O, d_i, d_O')

        label_dict = {
            f: "Frequency",
            T: "Time period",
        }

        ps = PintUnitSystem()
        T_val = random.randint(1, 60)
        f_val = 1/T_val
        
        var_values = {
            f: f_val * ps.convert_to_base_units('1/sec'),
            T: T_val * ps.convert_to_base_units('sec'),
        }


        lhs_symbol = f
        const_symbols = []
        rhs_symbols = [T]

        t_lhs = f
        t_const = 1
        t_rhs = 1/T
                                  
        eq = Eq(t_lhs, t_rhs)
                  
        data = {
            'prop_symbols': [lhs_symbol, const_symbols, rhs_symbols],
            'label_dict': label_dict,
            'var_values': var_values,
            'constant_value': t_const,
            'eq': eq,
            }

        return data
        pass

    pass
#class LightMechanicsHelper:

    