'''
Created on 16-Apr-2021

@author: rishi_priyansh

https://courses.lumenlearning.com/austincc-physics2/chapter/31-4-nuclear-decay-and-conservation-laws/
https://www.toppr.com/ask/content/story/amp/gamma-decay-problems-l2-76793/
'''
from sympy import symbols, Eq, solve, Symbol, latex, sqrt, UnevaluatedExpr
from xv.km.ui import SvgHelper
import matplotlib.pyplot as plt

import random
import inspect
import traceback

from ..helper import BaseHelper

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

class RadioActivityManager(BaseManager):
    '''
    RadioActivityManager
    Example:
        ke = RadioActivityManager()
        ke.getRandomProblem()
        ke.getRandomProblem(problem_type = 0)
        ...

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

        ke.printProblemTypes()

    '''
    _OPR_TYPE_COUNT = 10

    def __new__(cls, *args, **kwargs):
        instance = super(RadioActivityManager, cls).__new__(cls, *args, **kwargs)
        for base_class in RadioActivityManager.__bases__:
            base_class.__init__(instance, *args, **kwargs)
        return instance

    def __init__(self, *args, **kwargs):
        self.base_helper = BaseHelper(**kwargs)
        self.radio_activity_helper = self.base_helper.get_radio_activity_helper()
        pass



    def _init_problem_types(self, *args, **kwargs):
        self._append_problem_types([
            '_problem_radioactivity_overview',
            '_problem_radioactivity_in_periodic_table',
            '_problem_write_alpha_decay_equation',
            '_problem_write_beta_decay_equation',
            '_problem_write_positron_decay_equation',
            '_problem_write_gamma_decay_equation',
            '_problem_hydrogen_fusion_in_stars',
            '_problem_decay_equation_from_decay_series',
            '_problem_radioactive_decay_type',
            '_problem_write_decay_series_from_plot',
            #'_problem_deduce_radioactive_theory',
            #'_problem_calculate_half_life',
            #'_problem_calculate_radioactive_decay_constant',
            # https://byjus.com/jee/ie-irodov-solutions-part-6-radioactivity/
            '_problem_derive_radioactive_decay_equation',
            ])
        pass



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

        doc_style: xv_doc
        """
        category = 'radioactivity'
        wl_helper = self.base_helper.get_web_link_helper()
        result = wl_helper.get_links_for_category_as_strs(
                            category,
                            *args,
                            **kwargs)

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

        if result is None:
            problemTemplate.add_problem(f"""
            No result found matching:
                category = '{category}'
                args = {args}
                kwargs = {kwargs}
            """.strip(), 'text/html')
            return problemTemplate

        prob_s = f"""
        Overview of radioactivity.
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')

        soln_s = f"""

        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        Videos related to radioactivity:
        {result['anchors_str']}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate

        pass

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

        doc_style: xv_doc
        """
        ra_helper = self.radio_activity_helper

        periodic_trends_helper = self.base_helper.get_periodic_trends_helper()
        result = periodic_trends_helper.get_problem_radioactivity(*args, **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


    def _problem_write_alpha_decay_equation(self, *args, **kwargs):
        '''
        pass parameters:
        parent_atomic_number = 94
        parent_mass_number = 239
        '''
        ra_helper = self.radio_activity_helper

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

        decay_data = ra_helper.get_alpha_decay()
        decay_details = ra_helper.get_alpha_decay_problem_details(decay_data)

        problemTemplate.add_problem(decay_details['problem_s'].strip(), 'text/html')
        problemTemplate.add_solution(decay_details['soln_s'].strip(), 'text/html')

        problemTemplate.add_answer(decay_details['answer_s'].strip(), 'text/html')

        return problemTemplate

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

        doc_style: xv_doc
        """
        ra_helper = self.radio_activity_helper

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



        decay_data = ra_helper.get_beta_decay()
        decay_details = ra_helper.get_beta_decay_problem_details(decay_data)

        problemTemplate.add_problem(decay_details['problem_s'].strip(), 'text/html')
        problemTemplate.add_solution(decay_details['soln_s'].strip(), 'text/html')
        problemTemplate.add_answer(decay_details['answer_s'].strip(), 'text/html')

        print('TODO: Add info about anti neutrino')
        return problemTemplate

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

        doc_style: xv_doc
        """
        ra_helper = self.radio_activity_helper

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

        decay_data = ra_helper.get_positron_decay()
        decay_details = ra_helper.get_positron_decay_problem_details(decay_data)

        problemTemplate.add_problem(decay_details['problem_s'].strip(), 'text/html')
        problemTemplate.add_solution(decay_details['soln_s'].strip(), 'text/html')
        problemTemplate.add_answer(decay_details['answer_s'].strip(), 'text/html')

        print('TODO: Add info about neutrino')

        return problemTemplate

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

        doc_style: xv_doc
        """
        ra_helper = self.radio_activity_helper

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

        decay_data = ra_helper.get_gamma_decay()
        decay_details = ra_helper.get_gamma_decay_problem_details(decay_data)

        problemTemplate.add_problem(decay_details['problem_s'].strip(), 'text/html')
        problemTemplate.add_solution(decay_details['soln_s'].strip(), 'text/html')
        problemTemplate.add_answer(decay_details['answer_s'].strip(), 'text/html')

        return problemTemplate

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

        doc_style: xv_doc
        """
        ra_helper = self.radio_activity_helper

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


        prob_s = f"""
        Fusion of hydrogen in stars
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')

        soln_s = f"""
        <a href="https://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Fusion_in_the_Sun.svg/500px-Fusion_in_the_Sun.svg.png">Fusion of hydrogen in stars</a>

        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')


        answer_s = f"""
        <a href="https://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Fusion_in_the_Sun.svg/500px-Fusion_in_the_Sun.svg.png">Fusion of hydrogen in stars</a>

        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate




    def _problem_decay_equation_from_decay_series(self, *args, **kwargs):
        '''
        pass parameters:
        element_symbol or atomic_number
        mass_number

        '''
        ra_helper = self.radio_activity_helper

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

        atomic_input = ra_helper.parse_atomic_input(**kwargs)

        if not atomic_input['success']:
            isotopes = ra_helper.get_radioactive_isotopes()
            atomic_number, mass_number = random.choice(isotopes)
            kwargs['atomic_number'] = atomic_number
            kwargs['mass_number'] = mass_number
            atomic_input = ra_helper.parse_atomic_input(**kwargs)
            pass

        if not atomic_input['success']:
            problem_s = f"""
            Error: {atomic_input['error']}
            """
            problemTemplate.add_problem(problem_s.strip(), 'text/html')
            return problemTemplate

        element_symbol = atomic_input['element_symbol']
        #atomic_number = atomic_input['atomic_number']
        mass_number = atomic_input['mass_number']

        svg_str_series = ra_helper.plot_radioactive_decay_series(element_symbol, mass_number)


        decay_digraph = ra_helper.get_decay_digraph(element_symbol, mass_number)

        print(f"decay_digraph = {decay_digraph}")

        digraph, max_generation, max_xpos = decay_digraph

        self.digraph = digraph
        self.max_generation = max_generation
        self.max_xpos = max_xpos

        edges = list(digraph.edges)
        random_edge = random.choice(edges)
        decay_step = f""" {random_edge[0]} $\\rightarrow$ {random_edge[1]} """

        decay_type = digraph.edges.get(random_edge)['label']
        decay_type = decay_type.split("\n")
        decay_type[1] = float(decay_type[1]) * 100
        decay_type[1] = f"{decay_type[1]}%"
        #decay_type_str = ":".join(decay_type)
        decay_type_str = f"{decay_type[0]}"

        decay_details = ra_helper.get_decay_details(*random_edge, decay_type[0])

        problem_s = f"""
        The decay series for {element_symbol}-{mass_number} is given below.
        Write the decay equation for {decay_step}?

        {svg_str_series}
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')

        soln_s = f"""
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')


        answer_s = f"""
        <h2>Details of {decay_type_str} decay for {decay_step}:</h2>
        {decay_details['soln_s'].strip()}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate


    def _problem_radioactive_decay_type(self, *args, **kwargs):
        '''
        pass parameters:
        element_symbol or atomic_number
        mass_number
        '''
        ra_helper = self.radio_activity_helper

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


        atomic_input = ra_helper.parse_atomic_input(**kwargs)

        if not atomic_input['success']:
            isotopes = ra_helper.get_radioactive_isotopes()
            atomic_number, mass_number = random.choice(isotopes)
            kwargs['atomic_number'] = atomic_number
            kwargs['mass_number'] = mass_number
            atomic_input = ra_helper.parse_atomic_input(**kwargs)
            pass

        if not atomic_input['success']:
            problem_s = f"""
            Error: {atomic_input['error']}
            """
            problemTemplate.add_problem(problem_s.strip(), 'text/html')
            return problemTemplate

        element_symbol = atomic_input['element_symbol']
        #atomic_number = atomic_input['atomic_number']
        mass_number = atomic_input['mass_number']

        svg_str_series = ra_helper.plot_radioactive_decay_series(element_symbol, mass_number)

        digraph, max_generation, max_xpos = ra_helper.get_decay_digraph(element_symbol, mass_number)

        self.digraph = digraph
        self.max_generation = max_generation
        self.max_xpos = max_xpos

        edges = list(digraph.edges)
        random_edge = random.choice(edges)

        decay_type = digraph.edges.get(random_edge)['label']
        decay_type = decay_type.split("\n")
        decay_type[1] = float(decay_type[1]) * 100
        decay_type[1] = f"{decay_type[1]}%"
        decay_type_str = ":".join(decay_type)

        decay_step = f""" {random_edge[0]} $\\rightarrow$ {random_edge[1]} """
        problem_s = f"""
        The decay series for {element_symbol}-{mass_number} is given below.
        What is the decay type for {decay_step}?
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        problemTemplate.add_problem(svg_str_series, 'text/svg')

        soln_s = f"""
        Decay type for {decay_step} is {decay_type_str}.
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')


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

        return problemTemplate


    def _problem_write_decay_series_from_plot(self, *args, **kwargs):
        '''
        pass parameters:
        element_symbol or atomic_number
        mass_number
        '''
        ra_helper = self.radio_activity_helper

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

        atomic_input = ra_helper.parse_atomic_input(**kwargs)

        if not atomic_input['success']:
            isotopes = ra_helper.get_radioactive_isotopes()
            atomic_number, mass_number = random.choice(isotopes)
            kwargs['atomic_number'] = atomic_number
            kwargs['mass_number'] = mass_number
            atomic_input = ra_helper.parse_atomic_input(**kwargs)
            pass

        if not atomic_input['success']:
            problem_s = f"""
            Error: {atomic_input['error']}
            """
            problemTemplate.add_problem(problem_s.strip(), 'text/html')
            return problemTemplate

        element_symbol = atomic_input['element_symbol']
        #atomic_number = atomic_input['atomic_number']
        mass_number = atomic_input['mass_number']


        svg_str_series = ra_helper.plot_radioactive_decay_series(element_symbol, mass_number)
        result = ra_helper.plot_radioactive_decay_graph(element_symbol, mass_number)

        if result is None:
            problem_s = f"""
            Failed to write decay series for {element_symbol}-{mass_number}.
            """
            problemTemplate.add_problem(problem_s.strip(), 'text/html')
            return problemTemplate
            pass

        svg_str_graph, activities_str = result

        problem_s = f"""
        Write decay series for {element_symbol}-{mass_number}.
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')
        problemTemplate.add_problem(svg_str_graph, 'text/svg')

        soln_s = f"""
        decay series for {element_symbol}-{mass_number}.

        {activities_str}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')
        problemTemplate.add_solution(svg_str_series, 'text/svg')


        answer_s = f"""
        decay series for {element_symbol}-{mass_number}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate



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

        doc_style: xv_doc
        """

        ra_helper = self.radio_activity_helper
        result = ra_helper.get_problem_derive_radioactive_decay_equation(**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

