'''
Created on 20-Jan-2022

@author: bthakur
'''

import random
import inspect
import traceback

from sympy import (symbols, Symbol, pi, latex,
                   Rational)

from sympy.vector import express
import matplotlib.pyplot as plt


from xv.util import UtilClass, list_to_str, toIntOrFloat


# _vector_plotter_helper
# VectorPlotterHelper
        
class VectorPlotterHelper(UtilClass):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        pass

    def get_3d_vector(self, n1 = None, n2 = None, n3 = None, C = None):
        if n1 is None:
            n1 = random.randint(1, 9)
            
        if n2 is None:
            n2 = random.randint(1, 9)
            
        if n3 is None:
            n3 = random.randint(1, 9)
            
        from sympy import Matrix
        from sympy.vector import CoordSys3D, matrix_to_vector
        
        v = Matrix([n1, n2, n3])
        
        if C is None:
            C = CoordSys3D('')
            
        v = matrix_to_vector(v, C)
        return C, v
        pass

    def plot_3d_radius_vector(self, C, v, unit_vector = False):
        #source_code: start
        import numpy as np
        from xv.plotter import Plotter3D
        from xv.km.ui import SvgHelper  
        
        plotter = Plotter3D()
        
        C_origin = C.origin.position_wrt(C.origin)
        m_C_origin = C_origin.to_matrix(C)
        arr_C_origin = np.array(m_C_origin).astype(np.float64)[:].flatten()
        arr_v = np.array(v.to_matrix(C)).astype(np.float64)[:].flatten()
        
        plt.ioff()
        
        #plot v
        fig, ax = plotter.plot_vector(arr_C_origin, v, 
                                      color = 'red',
                                      opacity = 0.6,
                                      linewidth = 2)
        
        plotter.plot_cuboid(*arr_v, 
                            origin_at = "front-left-bottom",
                            ax = ax)
        
        #plot vx
        plotter.plot_vector(arr_C_origin, [arr_v[0], 0, 0], ax = ax)
        #plot vy
        plotter.plot_vector([arr_v[0], 0, 0], [arr_v[0], arr_v[1], 0], ax = ax)
        #plot vz
        plotter.plot_vector([arr_v[0], arr_v[1], 0], arr_v, ax = ax)
        
        
        plotter.plot_point(arr_C_origin, ax = ax, color = 'green')
        plotter.plot_point(arr_v, ax = ax, color = 'green')
        
        if unit_vector:
            v_norm = v.dot(v)
            arr_v_unit = arr_v * (1/v_norm)
            
            arr_v_unit = [np.float64(coeff) for coeff in arr_v_unit]
            
            plotter.plot_vector(arr_C_origin, arr_v_unit, 
                                ax = ax, color = 'black',
                                linewidth = 5,
                                arrow_length_ratio = 0.4)
            pass
            
        
        plt.gca().set_aspect('auto')
        
        svgHelper = SvgHelper()
        svg_str = svgHelper.plt_to_svg()
        plt.clf()
        plt.close()
        
        return svg_str, C_origin    
        pass
  
    def plot_3d_vector(self, p1, p2):
        #source_code: start
        import numpy as np
        from xv.plotter import Plotter3D
        from xv.km.ui import SvgHelper  
        
        plotter = Plotter3D()
        
        
        plt.ioff()
        
        #plot v
        fig, ax = plotter.plot_vector(p1, p2, 
                                      color = 'red',
                                      opacity = 0.6,
                                      linewidth = 2)
        
        
        plotter.plot_vector(p1, [p2[0], p1[1], p1[2]], ax = ax)
        plotter.plot_vector([p2[0], p1[1], p1[2]], [p2[0], p2[1], p1[2]], ax = ax)
        plotter.plot_vector([p2[0], p2[1], p1[2]], p2, ax = ax)
        
        plt.gca().set_aspect('auto')
        
        svgHelper = SvgHelper()
        svg_str = svgHelper.plt_to_svg()
        plt.clf()
        plt.close()
        
        return svg_str    
        pass
  

    def plot_2d_vector(self):
        #source_code: start
        import numpy as np
        from sympy import Matrix
        from sympy.vector import CoordSys3D, matrix_to_vector
        from xv.plotter import Plotter2D
        
        a, b = random.sample(range(-9, 10), 2)
        v = Matrix([a, b, 0])
        C = CoordSys3D('')
        v = matrix_to_vector(v, C)
        plotter = Plotter2D()
        
        C_origin = C.origin.position_wrt(C.origin)
        m_C_origin = C_origin.to_matrix(C)
        arr_C_origin = np.array(m_C_origin).astype(np.float64)[:-1].flatten()
        fig, ax = plotter.plot_vector(arr_C_origin, v)
        plt.gca().set_aspect('equal')
        
        #source_code: end
        
        result = {
            'C': C,
            'v': v,
            'fig': fig,
            'ax': ax,
            }
        
        return result    
        pass
  
    def plot_2d_vector_and_rotate(self):
        #source_code: start
        import numpy as np
        from sympy import Matrix
        from sympy.vector import CoordSys3D, matrix_to_vector
        from xv.plotter import Plotter2D
        
        a, b = random.sample(range(-9, 10), 2)
        
        v = Matrix([a, b, 0])
        C = CoordSys3D('')
        v = matrix_to_vector(v, C)
        
        #rotate vector
        theta  = random.choice([0, 30, 60, 90, 120, 180, 270, 360])
        theta_radians = np.radians(theta)
        
        
        D = C.orient_new_axis('D', - theta_radians, C.k)
        v_rotated = express(v, D)

        
        plotter = Plotter2D()
        
        C_origin = C.origin.position_wrt(C.origin)
        m_C_origin = C_origin.to_matrix(C)
        arr_C_origin = np.array(m_C_origin).astype(np.float64)[:-1].flatten()

        D_origin = D.origin.position_wrt(C.origin)
        m_D_origin = D_origin.to_matrix(D)
        arr_D_origin = np.array(m_D_origin).astype(np.float64)[:-1].flatten()

        fig, ax = plotter.plot_vector(arr_C_origin, v, color = '#cccccc')
        plotter.plot_vector(arr_D_origin, v_rotated, color = 'red', fig = fig,  ax = ax)
        plt.gca().set_aspect('equal')
        
        #source_code: end
        
        result = {
            'C': C,
            'v': v,
            'theta': theta,
            'v_rotated': v_rotated,
            'fig': fig,
            'ax': ax,
            }
        
        return result    
        pass
  
    def plot_2d_vector_and_move(self):
        #source_code: start
        import numpy as np
        from sympy import Matrix
        from sympy.vector import CoordSys3D, matrix_to_vector
        from xv.plotter import Plotter2D
        
        a, b = random.sample(range(-9, 10), 2)
        
        v = Matrix([a, b, 0])
        C = CoordSys3D('')
        v = matrix_to_vector(v, C)
        
        #move vector
        dx, dy = random.sample(range(-9, 10), 2)
        
        E = C.locate_new('E', dx * C.i + dy * C.j)
        v_moved = express(v, E) 

        
        plotter = Plotter2D()
        
        C_origin = C.origin.position_wrt(C.origin)
        m_C_origin = C_origin.to_matrix(C)
        arr_C_origin = np.array(m_C_origin).astype(np.float64)[:-1].flatten()
        
        E_origin = express(E.origin.position_wrt(C.origin), E)
        m_E_origin = E_origin.to_matrix(E)
        arr_E_origin = np.array(m_E_origin).astype(np.float64)[:-1].flatten()

        fig, ax = plotter.plot_vector(arr_C_origin, v, color = '#cccccc')
        plotter.plot_vector(arr_E_origin, v_moved, color = 'red', fig = fig,  ax = ax)
        plt.gca().set_aspect('equal')
        
        #source_code: end
        
        result = {
            'C': C,
            'v': v,
            'dx': dx,
            'dy': dy,
            'E_origin': E_origin,
            'v_moved': v_moved,
            'fig': fig,
            'ax': ax,
            }
        
        return result    
        pass
  
    def plot_2d_vector_and_rotate_and_move(self):
        #source_code: start
        import numpy as np
        from sympy import Matrix
        from sympy.vector import CoordSys3D, matrix_to_vector
        from xv.plotter import Plotter2D
        
        a, b = random.sample(range(-9, 10), 2)
        
        v = Matrix([a, b, 0])
        C = CoordSys3D('')
        v = matrix_to_vector(v, C)
        
        #rotate vector
        theta  = random.choice([0, 30, 60, 90, 120, 180, 270, 360])
        theta_radians = np.radians(theta)
        
        
        D = C.orient_new_axis('D', - theta_radians, C.k)
        v_rotated = express(v, D)

        dx, dy = random.sample(range(-9, 10), 2)
        E = D.locate_new('E', dx * D.i + dy * D.j)
        
        E_origin = express(E.origin.position_wrt(C.origin), E)
        m_E_origin = E_origin.to_matrix(E)
        arr_E_origin = np.array(m_E_origin).astype(np.float64)[:-1].flatten()
        
        v_moved = express(v_rotated, E)
        
        plotter = Plotter2D()
        
        C_origin = C.origin.position_wrt(C.origin)
        m_C_origin = C_origin.to_matrix(C)
        arr_C_origin = np.array(m_C_origin).astype(np.float64)[:-1].flatten()

        fig, ax = plotter.plot_vector(arr_C_origin, v, color = '#dddddd')
        plotter.plot_vector(arr_C_origin, v_rotated, color = '#000000', fig = fig,  ax = ax)
        plotter.plot_vector(arr_E_origin, v_moved, color = 'red', fig = fig,  ax = ax)
        plt.gca().set_aspect('equal')
        #source_code: end
        
        result = {
            'C': C,
            'v': v,
            'theta': theta,
            'v_rotated': v_rotated,
            'dx': dx,
            'dy': dy,
            'E_origin': E_origin,
            'v_moved': v_moved,
            'fig': fig,
            'ax': ax,
            }
        
        return result    
        pass
#class Geometry3dHelper:
