'''
Created on 12-Jul-2021

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

from sympy import (latex, Symbol, UnevaluatedExpr as ueval,
                   )
import sympy as sp
from xv.km.util import SympyUnitSystem

# _c_circuit_helper
# CCircuitHelper

from ._base_circuit_helper import BaseCircuitHelper

class CCircuitHelper(BaseCircuitHelper):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        pass

    def get_problem_circuit_C_resultant(self, **kwargs):

        sInfo = f"""Processing {self.__class__.__name__}.{inspect.stack()[0][3]}: """
        self._log(sInfo.strip())

        index = kwargs.get('index', None)

        try:

            if index is None:
                random_choices = list(range(1, 2))

                identifier = f"{self.__class__.__name__}{id(self)}.{inspect.stack()[0][3]}.random_choices"
                random_choice = self.get_no_repeat_random_choice(identifier, random_choices)
            else:
                random_choice = index

            if random_choice == 1:
                return self._get_mixed_C_circuit(**kwargs)

            return self._get_mixed_C_circuit(**kwargs)

        except Exception as e:
            sError = f"""Error {self.__class__.__name__}.{inspect.stack()[0][3]}: {e}
            """
            self._log(sError)
            self._log(traceback.format_exc())
            pass

        return None



    def _get_mixed_C_circuit(self, **kwargs):
        import schemdraw
        import matplotlib
        matplotlib.use('Agg')

        C = Symbol('C')
        C_unit = self._ss.to_unit('farad') # self._ss.to_unit('micro')

        arrange_types = {'s':'series', 'p':'parallel'}

        C_sets = []
        d = schemdraw.Drawing()

        prev_arrange_type = None

        for idx in range(random.randint(2, 4)):
            if prev_arrange_type == 's':
                arrange_type = "p"
            else:
                arrange_type = random.choice(list(arrange_types.keys()))

            if prev_arrange_type == 's':
                min_count = 2
            else:
                min_count = 2

            C_set = []
            for C_idx in range(random.randint(min_count, 4)):
                C_val = ueval(random.randint(1, 5)) * C_unit
                C_set.append(C_val)
                pass

            C_sets.append([C_set, arrange_type])

            d_set = self._draw_C_set(d, C_set, arrange_type)
            prev_arrange_type = arrange_type
            pass

        svg_str = self._convert_d_to_svg_str(d)

        prob_s = f"""
        Draw the simplified circuit and find voltage, resistance and current in the circuit.
        {svg_str}
        """

        soln_stmts = []

        C_sets_mod = []
        C_parallel_sums_ltx = []
        for C_set, arrange_type in C_sets:
            if arrange_type != 'p':
                C_sets_mod.extend(C_set)
                continue

            C_set_sum_ltx = " + ".join([f"{latex(item)}" for item in C_set])
            C_set_sum_ltx = f"{C_set_sum_ltx} = {latex(sum(C_set).simplify())}"

            C_parallel_sums_ltx.append(C_set_sum_ltx)
            C_sets_mod.append(sum(C_set).simplify())
            pass


        C_parallel_sums_ltx = " \\\\ \\\\ & ".join(C_parallel_sums_ltx)


        soln_stmt = f"""
        Let us simplify the parallely arranged capacitances.


        $\\displaystyle
        \\begin{{aligned}}

        & \\; {C_parallel_sums_ltx}
        \\\\ \\\\

        \\end{{aligned}}
        $
        """
        soln_stmts.append(soln_stmt.strip())


        C_sets_mod_sum_ltx = [f"\\frac{{ 1 }} {{ {latex(item)} }}" for item in C_sets_mod]
        C_sets_mod_sum_ltx = " + ".join(C_sets_mod_sum_ltx)

        inv_sum = sum([1 / item for item in C_sets_mod]).simplify()
        C_val = (1 / inv_sum).simplify()

        d_simplified = schemdraw.Drawing()
        self._draw_series_C_set(d_simplified, C_sets_mod)
        svg_str_simplified = self._convert_d_to_svg_str(d_simplified)

        soln_stmt = f"""
        Now all capacitances are arranged in a series.
        {svg_str_simplified}

        $\\displaystyle
        \\begin{{aligned}}

        & \\; {latex(1 / C)} = {C_sets_mod_sum_ltx}
        \\\\ \\\\

        \\implies
        & \\; {latex(1 / C)} = {latex(inv_sum)}
        \\\\ \\\\

        \\implies
        & \\; {latex(C)} = {latex(C_val)}
        \\\\ \\\\

        \\end{{aligned}}
        $
        """
        soln_stmts.append(soln_stmt.strip())


        soln_s = "\n\n".join(soln_stmts)

        answer_s = f"""
        $\\displaystyle
        {latex(C_val)}
        $
        """

        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result



    def _draw_C_set(self, d, C_set, arrange_type):
        if arrange_type == 's':
            return self._draw_series_C_set(d, C_set)

        return self._draw_parallel_C_set(d, C_set)
        pass

    def _draw_series_C_set(self, d, C_set):
        import schemdraw.elements as elm

        for C_temp in C_set:
            d.add(elm.Capacitor().label(f'${latex(C_temp)}$', loc = "top"))

        return d
        pass

    def _draw_parallel_C_set(self, d, C_set):
        import schemdraw.elements as elm

        std_length = d.unit * .75

        start_line = d.add( elm.Line(d='right', l = std_length ))

        for C_idx, C_temp in enumerate(C_set):
            d.push()
            L_length = std_length * (C_idx + 1)

            L_up = d.add(elm.Line(d='up', l=L_length))
            d.add(elm.Capacitor(d='right', start = L_up.end
                               ).label(f'${latex(C_temp)}$',
                                       loc = "top",
                                       ))
            L_up = d.add(elm.Line(d='down', l=L_length))
            if C_idx < len(C_set) - 1:
                d.pop()
            pass

        end_line = d.add( elm.Line(d='right', l = std_length ))
        return d
        pass

    pass
#class CCircuitHelper:

