'''
Created on 12-Jul-2021

@author: bthakur
'''
import random
import inspect
import traceback   #        {inspect.stack()[0][3]}

import re
from sympy import (Eq, symbols, sqrt, latex,
                   Rational, solve, log, nsimplify, E, exp,  
                   sin, cos, I, series, pi)
from sympy.abc import theta
import sympy

from ....util import LatexEquation, MathUtil

from xv.km.util import latex_fraction

from xv.util import UtilClass

class ModellingLcmHelper(UtilClass):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        pass


    def get_random_model(self, **kwargs):
        methods = [
                    #self.model_min_common_volume,
                    #self.model_first_common_meeting,
                    self.model_first_common_time,
                   ]
        
        method = random.choice(methods)
        return method()
        pass


    def model_min_common_volume(self):
        V1, V2, V3, n1, n2, n3, CV = symbols('V_1, V_2, V_3, n_1, n_2, n_3, V_c')
        
        var_names = {V1: 'volume of first container',
                     V2: 'volume of second container',
                     V3: 'volume of third container',
                     n1: 'times first container is used',
                     n2: 'times second container is used',
                     n3: 'times third container is used',
                     CV: 'minimum common volume',
                     }
        
        V1_val = random.randint(3, 20)
        V2_val = random.randint(2, 20)
        V3_val = random.randint(2, 20)
        CV_val = MathUtil.lcm(V1_val, V2_val, V3_val)
        
        n1_val = CV_val // V1_val
        n2_val = CV_val // V2_val
        n3_val = CV_val // V3_val

        vals_dict = {
                     V1: V1_val,
                     V2: V2_val,
                     V3: V3_val,
                     CV: CV_val,
                     n1: n1_val,
                     n2: n2_val,
                     n3: n3_val,
                    }
        
        var_vals = self._get_filtered_dict(vals_dict, [V1, V2, V3])
        solutions = self._get_filtered_dict(vals_dict, [CV, n1, n2, n3])
        
        statement_header = ''
        statement = f"""
        Three measuring containers are have capacity of {V1_val}, {V2_val} and {V3_val} liters. 
        """
        statement_footer = "What is the minimum volume that we can measure?"

        eq1 = Eq(V1_val * n1, CV )
        latex_eq1 = LatexEquation(f"{V1_val} * {latex(n1)}",
                                  latex(CV),
                                  eq1)
        
        eq2 = Eq(V2_val * n2, CV )
        latex_eq2 = LatexEquation(f"{V2_val} * {latex(n2)}",
                                  latex(CV),
                                  eq2)

        eq3 = Eq(V3_val * n3, CV )
        latex_eq3 = LatexEquation(f"{V3_val} * {latex(n3)}",
                                  latex(CV),
                                  eq3)

        latex_eqs = [latex_eq1, latex_eq2, latex_eq3]
        eqs_str = self._get_eqs_str(latex_eqs)
        

        random_model = {
            'statement_header': statement_header,
            'statement': statement,
            'statement_footer': statement_footer,
            'var_names': var_names,
            'latex_eqs': latex_eqs,
            'eqs_str': eqs_str,
            'var_names': var_names,
            'var_vals': var_vals,
            'solutions': solutions,
            }
        
        return random_model
        pass

    def model_first_common_meeting(self):
        d1, d2, d3, n1, n2, n3, cd = symbols('d_1, d_2, d_3, n_1, n_2, n_3, d_c')
        
        var_names = {d1: 'distance covered by first friend each time',
                     d2: 'distance covered by second friend each time',
                     d3: 'distance covered by third friend each time',
                     n1: 'times first friend runs',
                     n2: 'times second friend runs',
                     n3: 'times third friend runs',
                     cd: 'minimum common distance',
                     }
        
        d1_val = random.randint(2, 20)
        d2_val = random.randint(2, 20)
        d3_val = random.randint(2, 20)
        cd_val = MathUtil.lcm(d1_val, d2_val, d3_val)
        
        n1_val = cd_val // d1_val
        n2_val = cd_val // d2_val
        n3_val = cd_val // d3_val

        vals_dict = {
                     d1: d1_val,
                     d2: d2_val,
                     d3: d3_val,
                     cd: cd_val,
                     n1: n1_val,
                     n2: n2_val,
                     n3: n3_val,
                    }
        
        var_vals = self._get_filtered_dict(vals_dict, [d1, d2, d3])
        solutions = self._get_filtered_dict(vals_dict, [cd, n1, n2, n3])
        
        statement_header = ''
        statement = f"""
        Three friends walk {d1_val}, {d2_val} and {d3_val} meters at one time.
        They stop when they are ahead and wait for others to meet or cross them. 
        When will they meet together after starting from the same place?
        """
        statement_footer = "What is the minimum volume that we can measure?"

        eq1 = Eq(d1_val * n1, cd )
        latex_eq1 = LatexEquation(f"{d1_val} * {latex(n1)}",
                                  latex(cd),
                                  eq1)
        
        eq2 = Eq(d2_val * n2, cd )
        latex_eq2 = LatexEquation(f"{d2_val} * {latex(n2)}",
                                  latex(cd),
                                  eq2)

        eq3 = Eq(d3_val * n3, cd )
        latex_eq3 = LatexEquation(f"{d3_val} * {latex(n3)}",
                                  latex(cd),
                                  eq3)

        latex_eqs = [latex_eq1, latex_eq2, latex_eq3]
        eqs_str = self._get_eqs_str(latex_eqs)
        

        random_model = {
            'statement_header': statement_header,
            'statement': statement,
            'statement_footer': statement_footer,
            'var_names': var_names,
            'latex_eqs': latex_eqs,
            'eqs_str': eqs_str,
            'var_names': var_names,
            'var_vals': var_vals,
            'solutions': solutions,
            }
        
        return random_model
        pass

    
    def model_first_common_time(self):
        d1, d2, d3, n1, n2, n3, cd = symbols('d_1, d_2, d_3, n_1, n_2, n_3, d_c')
        
        var_names = {d1: 'distance covered by first friend each time',
                     d2: 'distance covered by second friend each time',
                     d3: 'distance covered by third friend each time',
                     n1: 'times first friend runs',
                     n2: 'times second friend runs',
                     n3: 'times third friend runs',
                     cd: 'minimum common distance',
                     }
        
        d1_val = random.randint(2, 20)
        d2_val = random.randint(2, 20)
        d3_val = random.randint(2, 20)
        cd_val = MathUtil.lcm(d1_val, d2_val, d3_val)
        
        n1_val = cd_val // d1_val
        n2_val = cd_val // d2_val
        n3_val = cd_val // d3_val

        vals_dict = {
                     d1: d1_val,
                     d2: d2_val,
                     d3: d3_val,
                     cd: cd_val,
                     n1: n1_val,
                     n2: n2_val,
                     n3: n3_val,
                    }
        
        var_vals = self._get_filtered_dict(vals_dict, [d1, d2, d3])
        solutions = self._get_filtered_dict(vals_dict, [cd, n1, n2, n3])
        
        statement_header = ''
        statement = f"""
        "On the coast there are three lighthouses.
        The first light shines for {d1_val} seconds, then is off for {d1_val} seconds.
        The second light shines for {d2_val} seconds, then is off for {d2_val} seconds.
        The third light shines for {d3_val} seconds, then is off for {d3_val} seconds.
        When will all three lights come on together?
        """
        statement_footer = "What is the minimum volume that we can measure?"

        eq1 = Eq(d1_val * n1, cd )
        latex_eq1 = LatexEquation(f"{d1_val} * {latex(n1)}",
                                  latex(cd),
                                  eq1)
        
        eq2 = Eq(d2_val * n2, cd )
        latex_eq2 = LatexEquation(f"{d2_val} * {latex(n2)}",
                                  latex(cd),
                                  eq2)

        eq3 = Eq(d3_val * n3, cd )
        latex_eq3 = LatexEquation(f"{d3_val} * {latex(n3)}",
                                  latex(cd),
                                  eq3)

        latex_eqs = [latex_eq1, latex_eq2, latex_eq3]
        eqs_str = self._get_eqs_str(latex_eqs)
        

        random_model = {
            'statement_header': statement_header,
            'statement': statement,
            'statement_footer': statement_footer,
            'var_names': var_names,
            'latex_eqs': latex_eqs,
            'eqs_str': eqs_str,
            'var_names': var_names,
            'var_vals': var_vals,
            'solutions': solutions,
            }
        
        return random_model
        pass

    
    def _get_eqs_str(self, latex_eqs):
        eqs_str = [f'$\\displaystyle {latex_eq}$' for latex_eq in latex_eqs]
        eqs_str = "\n\n".join(eqs_str)
        return eqs_str
        pass
    
    def _get_filtered_dict(self, dct, keys):
        return {k:dct[k] for k in keys}
        pass
    
    
    pass
#class ModellingLcmHelper:
