'''
Created on 12-Jul-2021

@author: rishi_priyansh
'''
import random
import inspect
import traceback
import re
import operator
import datetime
import calendar
from time import time, ctime

from sympy import (symbols, latex, simplify, nsimplify, 
                   Rational,
                   Eq,
                   pi,
                   sin, cos, tan,
                   csc, sec, cot
                   )
from sympy.abc import theta
from sympy.physics import units

from xv.km.util import latex_fraction, latex_exponent, wrap_bracket
from xv.math.util import LatexEquation
from xv.km.ui import SvgHelper         


class ForceFieldHelper:
    def __init__(self, b = None, e = None, count = 2, **kwargs):
        self.verbose = kwargs.get('verbose', False)
        self.implies = symbols(u'\U000021D2')
        
        self._colors = ['indigo', 'blue', 'green', 'red', 'cyan', 'magenta', 
                        'violet', 'black', 'orange', 'black', 'grey']  
        self._markers = ['o', 'v', '^', '<', '>', '1', '2', '3', '4', 
                         '8', 's', 'p', 'P', '*', 'h', 'H', 'X', 'D', 'd', 'o']
        self._p_labels = 'ABCDEFGHIJKLMNPQRSTUVWXYZ'

        self._center_label = 'O'
        self._center = (0, 0)

        self._default_font_size = 10
        self._default_fig_size = 6
        self._axis_multiplier = 1.2
        pass

    def get_gravitational_field(self):
        E = symbols('E')
        r = symbols('r')
        eq = Eq(E, units.G * units.m / r **2)
        
        lhs_latex = latex(E)
        rhs_latex = latex_fraction(latex(units.m), latex(r**2))
        rhs_latex = f"{latex(units.G)} * {rhs_latex}"
        latex_eq = LatexEquation(lhs_latex, rhs_latex, eq)
        return latex_eq
        pass

    def plot_gravitational_field_due_to_a_point_mass(self):
        latex_eq = self.get_gravitational_field()
        unit_circle_codes = self._plot_code_circle()
        r = (random.randint(8, 9), random.randint(6, 7))
        r0 = (0, 0)

        custom_code = f"""
            import matplotlib.pyplot as plt
            import numpy as np
            from numpy import linspace, pi, sin, cos
            fig = plt.figure(figsize=(6, 6))

            #plot center
            plt.plot({r0[0]}, {r0[1]}, marker = 'o', color = 'grey', markersize = 10)
            plt.gca().annotate('O ({r0[0]}, {r0[1]})', xy=(0+1, 0+1), xycoords='data', fontsize=10)

            plt.plot({r[0]}, {r[1]}, marker = 'o', color = 'grey', markersize = 10)
            plt.gca().annotate('P ({r[0]}, {r[1]})', xy=({r[0]}+1, {r[1]}+1), xycoords='data', fontsize=10)

            plt.quiver([{r0[0]}],[{r0[1]}],[{r[0]}],[{r[1]}],
                      angles='xy', scale_units='xy', scale=1.)
            
            plt.quiver([{r[0]}],[{r[1]}],[{r[0]/2}],[{r[1]/2}],
                      angles='xy', scale_units='xy', scale=1., color = 'red')
            
            #plot circle
            #plt.plot(xs, ys, color = 'grey')
            
            #optional code
            plt.xlim({-r[0] - 5}, {r[0] + 5})
            plt.ylim({-r[1] - 5}, {r[1] + 5})
            plt.gca().set_aspect('equal')
            plt.axis('off')
        """
        
        #print(custom_code)
                
        svgHelper = SvgHelper()
        svg_str, plot_code = svgHelper.get_svg_data(custom_code, strip_lines = True)
        
        #in jupyter notebook, see
        #    HTML(SVG(svg_str).data)
        #    SVG(svg_str)
        return svg_str, plot_code
        pass

    def get_electric_field(self):
        E = symbols('E')
        #scipy.constants.epsilon_0
        Q = units.charge.symbol
        epsilon_0 = symbols('epsilon_0')
        r = symbols('r')
        eq = Eq(E,  Q / (4 * pi * epsilon_0 * r **2))
        
        lhs_latex = latex(E)
        constant_latex = latex_fraction(1, f"4{latex(pi)}{latex(epsilon_0)}")
        qr_inv_sqr_latex = latex_fraction(latex(Q), latex(r ** 2))
        rhs_latex = f"{constant_latex} * {qr_inv_sqr_latex}"
        latex_eq = LatexEquation(lhs_latex, rhs_latex, eq)
        return latex_eq
        pass

    def get_var_latex(self, v):
        if len(f"{v}") == 1:
            v_latex = f"{v}"
            return v_latex
        
        v_latex = f"\\left({latex(v)}\\right)"
        if isinstance(v, int):
            if v > 0:
                v_latex = f"{v}"
            pass

        return v_latex  


    def _plot_code_circle(self, center = None, axis_off = True, axis_lim = None):
        if center is None:
            center = self._center

        if center == (0, 0):
            s_xs_ys = f"""
            xs = cos(angles)
            ys = sin(angles)
            """
        else:
            s_xs_ys = f"""
            xs = {center[0]} + cos(angles)
            ys = {center[1]} + sin(angles)
            """
        if axis_off:
            s_axis_off = "plt.axis('off')"
        else:
            s_axis_off = ""
            
        if axis_lim is None:
            axis_lim = max(abs(center[0]), abs(center[1])) + self._axis_multiplier
        
        idx = -1
        marker = self._markers[idx]
        color = self._colors[idx]
        markersize = self._default_font_size

        code_0 = f"""
            import numpy as np
            from numpy import linspace, pi, sin, cos
            fig = plt.figure(figsize=({self._default_fig_size}, {self._default_fig_size}))

            angles = linspace(0 * pi, 2 * pi, 100 )
            """
        code_1 = f"""
            {s_xs_ys.strip()}
            {self._code_piece_circle(center, marker, color, markersize)}
        """
        code_2 = f"""
            #optional code
            plt.xlim(-{axis_lim}, {axis_lim})
            plt.ylim(-{axis_lim}, {axis_lim})
            plt.gca().set_aspect('equal')
            {s_axis_off}
        """
        return (code_0, code_1, code_2)
        pass

    def _code_piece_circle(self, center, marker, color, markersize):
        circle_code = f"""
            #plot center
            plt.plot({center[0]}, {center[1]}, marker = '{marker}', color = '{color}', markersize = {markersize})
            plt.gca().annotate('{self._center_label} ({center[0]}, {center[1]})', xy=({center[0]}-0.20, {center[1]}-0.12), xycoords='data', fontsize={self._default_font_size})

            #plot circle
            plt.plot(xs, ys, color = '{color}')
        """
        
        return circle_code
        pass


        
    pass
#class ForceFieldHelper:
