'''
Created on 16-Apr-2021

@author: bthakur
'''
import os
import numpy as np
import random
import inspect
import traceback

from xv.km.ui import SvgHelper

from sympy.core.expr import UnevaluatedExpr as ueval
from xv.km.util import latex_fraction

from ..helper import BaseHelper
from xv.km.managers import BaseManager
from xv.km.kelements import KProblemTemplate
import matplotlib.pylab as plt
import numpy as np
from xv.util import strip_source_code_tabs, get_function_source_code


class Vector3dManager(BaseManager):
    '''
    Circle and its geometry
    Example:
        ke = Vector3dManager()
        ke

        ke.printProblemTypes()

        ke.getRandomProblem()
        ke.getRandomProblem(problem_type = 0)
        ke.getRandomProblem(problem_type = 1)
        ...

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

        ke.printLength(2, 5, 3, -1)
        ke.printMovementLengths()


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

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



    def _init_problem_types(self, *args, **kwargs):
        self._append_problem_types([
            '_problem_sample',
            # https://www.nagwa.com/en/explainers/373101390857/
            '_problem_plot_a_point',
            '_problem_plot_a_line',
            '_problem_plot_a_plane',
            # '_problem_describe_point_in_different_ways',
            '_problem_equation_of_a_line',
            '_problem_equation_of_a_plane',
            '_problem_plane_through_a_point_and_given_normal_vector',
            '_problem_plane_through_a_point_and_parallel_to_2_vectors',
            '_problem_plane_through_3_points',
            '_problem_plane_through_2_lines',


         ])
        pass


    def _problem_sample(self, *args, **kwargs):
        v3d_helper = self.base_helper.get_vector_helper().get_vector_3d_helper()

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

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

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

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

        return problemTemplate
        pass

    def _problem_plot_a_point(self, *args, **kwargs):
        from xv.plotter.helper import BaseHelper as PlotterBaseHelper
        plotter_base_helper = PlotterBaseHelper(verbose = self.verbose)
        v3d_helper = self.base_helper.get_vector_helper().get_vector_3d_helper()

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

        p1 = np.random.randint(-5, 5, size = 3)

        use_cache = kwargs.get('use_cache', True)
        refresh_cache = kwargs.get('refresh_cache', False)

        plot_code, svg_str = plotter_base_helper.call_plot_method(v3d_helper.plot_point,
                                                                  p1 = p1,
                                                                  use_cache = use_cache,
                                                                  refresh_cache = refresh_cache)

        prob_s = f"""
        Plot the point ({p1[0]}, {p1[1]}, {p1[2]}).
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')



        problemTemplate.add_solution(svg_str, 'text/svg')
        soln_s = f"""
        <h2>PLot Code:</h2>
        <pre>{plot_code}</pre>
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        problemTemplate.add_answer(svg_str, 'text/svg')

        return problemTemplate
        pass

    def _problem_plot_a_line(self, *args, **kwargs):
        v3d_helper = self.base_helper.get_vector_helper().get_vector_3d_helper()

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

        plt.ioff()
        plt.figure(figsize = (13, 6))
        n = np.array([2, 3, -3])
        p1 = np.array([1, -2, -3])
        v3d_helper.plot_line(p1, n)
        svgHelper = SvgHelper()
        svg_str = svgHelper.plt_to_svg()
        #plt.figure().clear()
        plt.clf()
        plt.close()


        prob_s = f"""
        plot a plame in 3D coordinates
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')

        problemTemplate.add_solution(svg_str, 'text/svg')
        soln_s = f"""
        import matplotlib.pylab as plt
        import numpy as np

        n = np.array([2, 3, -3])
        p1 = np.array([1, -2, -3])

        steps = 100
        t = np.linspace(-10, 10, steps)
        x = p1[0] + n[0]*t
        y = p1[1] + n[1]*t
        z = p1[2] + n[2]*t
        origin = np.array([0, 0, 0])

        fig = plt.figure(figsize = (6, 6))
        ax = plt.axes(projection='3d', box_aspect = (1, 1, 1))

        ax.plot(*origin, color = 'blue', marker = 'o')
        ax.text(origin[0] + 0.25, origin[1] + 0.25, origin[2] + 0.25, s = 'O', fontsize = 12)

        ax.plot(x, y, z, color= 'red')

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

        answer_s = f"""
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        problemTemplate.add_answer(svg_str, 'text/svg')

        return problemTemplate
        pass

    def _problem_plot_a_plane(self, *args, **kwargs):
        v3d_helper = self.base_helper.get_vector_helper().get_vector_3d_helper()

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

        plt.ioff()
        plt.figure(figsize = (13, 6))
        n = np.array([2, 3, -3])
        d = 4
        v3d_helper.plot_plane(n, d)
        svgHelper = SvgHelper()
        svg_str = svgHelper.plt_to_svg()
        #plt.figure().clear()
        plt.clf()
        plt.close()


        prob_s = f"""
        plot a plame in 3D coordinates
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')

        problemTemplate.add_solution(svg_str, 'text/svg')
        soln_s = f"""
        import matplotlib.pylab as plt
        import numpy as np

        steps = 100
        x = np.linspace(-10, 10, steps)
        y = np.linspace(-10, 10, steps)
        X,Y = np.meshgrid(x,y)
        n = [{n[0]}, {n[1]}, {n[2]}]
        d = {d}

        Z = -(n[0]*X + n[1]*Y + d)/n[2]
        origin = np.array([0, 0, 0])

        fig = plt.figure(figsize = (6, 6))
        ax = plt.axes(projection='3d', box_aspect = (1, 1, 1))

        ax.plot(*origin, color = 'blue', marker = 'o')
        ax.text(origin[0] + 0.25, origin[1] + 0.25, origin[2] + 0.25, s = 'O', fontsize = 12)

        ax.plot_surface(X, Y, Z, color= 'red', alpha = 0.5)

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

        answer_s = f"""
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        problemTemplate.add_answer(svg_str, 'text/svg')

        return problemTemplate
        pass

    def _problem_equation_of_a_line(self, *args, **kwargs):
        v3d_helper = self.base_helper.get_vector_helper().get_vector_3d_helper()

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

        plt.ioff()
        plt.figure(figsize = (13, 6))
        origin = np.array([0, 0, 0])
        n = np.array([9, 8, 6])
        p1 = np.array([-8, -2, 8])

        var_t = 3
        var_x = p1[0] + n[0]*var_t
        var_y = p1[1] + n[1]*var_t
        var_z = p1[2] + n[2]*var_t
        q1 = np.array([var_x, var_y, var_z])

        v3d_helper.plot_line(p1, n)
        ax = plt.gca()
        ax.plot(*p1, marker = 'o', color = 'blue')
        ax.quiver(*p1, *n, label = r'$\vec{n}$', color = 'green')
        ax.quiver(*origin, *p1, label = r'$\vec{r_0}$', color = 'purple')
        ax.quiver(*origin, *q1, label = r'$\vec{r}$', color = 'lightgreen')
        ax.legend()

        svgHelper = SvgHelper()
        svg_str = svgHelper.plt_to_svg()
        #plt.figure().clear()
        plt.clf()
        plt.close()

        prob_s = f"""
        Explain the equation of line
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')

        problemTemplate.add_solution(svg_str, 'text/svg')
        soln_s = f"""
        $\\vec{{n}}$ is the direction vector
        $\\vec{{r}}$ is the vector of any arbitrary point
        $\\vec{{n}}$ is the vector of a given point
        $$
        \\begin{{aligned}}
        & \\vec{{n}}=(a, b, c) \\\\
        & \\vec{{r}}=(x, y, z) \\\\
        & \\vec{{r}}_0=\\left(x_0, y_0, z_0\\right)
        \\end{{aligned}}
        $$
        $$
        \\begin{{aligned}}
        & t \\vec{{n}}=\\vec{{r}}-\\vec{{r}}_0 \\\\
        & \\implies t(a, b, c)=(x, y, z)-\\left(x_0, y_0, z_0\\right) \\\\
        & \\implies(a t, b t, c t)=\\left(x-x_0, y-y_0, z-z_0\\right) \\\\
        & \\implies\\left\\{{\\begin{{array}}{{l}}
        a t=x-x_0 \\\\
        b t=y-y_0 \\\\
        c t=z-z_0
        \\end{{array}}\\right.
        \\end{{aligned}}
        $$

        This is the line equation in $3 d$
        $$
        \\begin{{aligned}}
        & a t=x-x_0 \\\\
        & b t=y-y_0 \\\\
        & c t=z-z_0
        \\end{{aligned}}
        $$

        Also
        $$
        \\frac{{x-x_0}}{{a}}=\\frac{{y-y_0}}{{b}}=\\frac{{z-z_0}}{{c}}=t
        $$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        see solution
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate
        pass

    def _problem_equation_of_a_plane(self, *args, **kwargs):
        v3d_helper = self.base_helper.get_vector_helper().get_vector_3d_helper()

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

        plt.ioff()
        plt.figure(figsize = (13, 6))
        origin = np.array([0, 0, 0])
        p1 = np.array([-8, -2, 8])

        n = np.array([-2, -3, 3])
        d = -(n[0]*p1[0] + n[1]*p1[1] + n[2]*p1[2])
        var_x = 3
        var_y = 5
        var_z = -(n[0]*var_x + n[1]*var_y + d)/n[2]
        q1 = np.array([var_x, var_y, var_z])

        v3d_helper.plot_plane(n, p1 = p1)

        ax = plt.gca()
        ax.plot(*p1, marker = 'o', color = 'blue')
        ax.quiver(*p1, *n, label = r'$\vec{n}$', color = 'green')
        ax.quiver(*origin, *p1, label = r'$\vec{r_0}$', color = 'purple')
        ax.quiver(*origin, *q1, label = r'$\vec{r}$', color = 'lightgreen')
        ax.quiver(*p1, *(q1-p1), label = r'$\vec{r}$', color = 'cyan')
        ax.legend()

        svgHelper = SvgHelper()
        svg_str = svgHelper.plt_to_svg()
        #plt.figure().clear()
        plt.clf()
        plt.close()

        prob_s = f"""
        Explain the equation of plane
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')

        problemTemplate.add_solution(svg_str, 'text/svg')
        soln_s = f"""
        $\\vec{{n}}$ is the normal vector to plane
        $\\vec{{r}}$ is the vector of any arbitrary point
        $\\vec{{n}}$ is the vector of a given point
        $$
        \\begin{{aligned}}
        & \\vec{{n}}=(a, b, c) \\\\
        & \\vec{{r}}=(x, y, z) \\\\
        & \\vec{{r}}_0=\\left(x_0, y_0, z_0\\right)
        \\end{{aligned}}
        $$
        $$
        \\begin{{aligned}}
        & \\left(\\vec{{r}}-\\vec{{r}}_0\\right) \\cdot \\vec{{n}}=0 \\\\
        \\implies & \\left(x-x_0, y-y_0, z-z_0\\right) \\cdot(a, b, c)=0 \\\\
        \\implies & a\\left(x-x_0\\right)+b\\left(y-y_0\\right)+c\\left(z-z_0\\right)=0 \\\\
        \\implies & a x+b y+c z-\\left(a x_0+b y_0+c z_0\\right)=0 \\\\
        \\implies & a x+b y+c z+d=0 \\quad d=-\\left(a x_0+b y_0+c z_0\\right)
        \\end{{aligned}}
        $$

        This is general form of plane equation
        $$
        a x+b y+c z+d=0
        $$

        This is scalar form of plane equation
        $$
        a x+b y+c z-\\left(a x_0+b y_0+c z_0\\right)=0
        $$

        This rector form of plane equation
        $$
        \\left(\\vec{{r}}-\\vec{{r}}_0\\right) \\cdot \\vec{{n}}=0
        $$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        see solution
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate
        pass

    def _problem_plane_through_a_point_and_given_normal_vector(self, *args, **kwargs):
        v3d_helper = self.base_helper.get_vector_helper().get_vector_3d_helper()

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

        plt.ioff()
        plt.figure(figsize = (13, 6))
        origin = np.array([0, 0, 0])
        p1 = np.array([3, 3, 15])
        p2 = np.array([9, 2, 15])
        p3 = np.array([6, 8, 15])

        r_1 = p2 - p1
        r_2 = p3 - p1
        n = np.cross(r_1, r_2)
        d = -(n[0]*p1[0] + n[1]*p1[1] + n[2]*p1[2])
        var_x = np.random.randint(-10, 10)
        var_y = np.random.randint(-10, 10)
        var_z = -(n[0]*var_x + n[1]*var_y + d)/n[2]
        q1 = np.array([var_x, var_y, var_z])

        v3d_helper.plot_plane(n, p1 = p1)

        ax = plt.gca()
        ax.plot(*p1, marker = 'o', color = 'blue')
        ax.quiver(*p1, *n, label = r'$\vec{n}$', color = 'green')
        ax.quiver(*origin, *p1, label = r'$\vec{r_0}$', color = 'purple')
        ax.quiver(*origin, *q1, label = r'$\vec{r}$', color = 'lightgreen')
        ax.quiver(*p1, *(q1-p1), label = r'$\vec{r}$', color = 'cyan')
        ax.legend()

        svgHelper = SvgHelper()
        svg_str = svgHelper.plt_to_svg()
        #plt.figure().clear()
        plt.clf()
        plt.close()

        prob_s = f"""
        Give the equation of plane which contains the point ({p1[0]}, {p1[1]}, {p1[2]}) and has a normal vector ({n[0]}, {n[1]}, {n[2]})
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')

        problemTemplate.add_solution(svg_str, 'text/svg')
        soln_s = f"""
        $\\vec{{n}}$ is the normal vector to plane
        $\\vec{{r}}$ is the vector of any arbitrary point
        $\\vec{{n}}$ is the vector of a given point
        $$
        \\begin{{aligned}}
        & \\vec{{n}}=(a, b, c) \\\\
        & \\vec{{r}}=(x, y, z) \\\\
        & \\vec{{r}}_0=\\left(x_0, y_0, z_0\\right)
        \\end{{aligned}}
        $$
        $$
        \\begin{{aligned}}
        & \\left(\\vec{{r}}-\\vec{{r}}_0\\right) \\cdot \\vec{{n}}=0 \\\\
        & \\implies\\left(x-{p1[0]}, y-{p1[1]}, z-{p1[2]}\\right) \\cdot({n[0]}, {n[1]}, {n[2]})=0 \\\\
        & \\implies {n[0]}\\left(x-{p1[0]}\\right)+{n[1]}\\left(y-{p1[1]}\\right)+{n[2]}\\left(z-{p1[2]}\\right)=0 \\\\
        & \\implies {n[0]} x + {n[1]} y + {n[2]} z + {d}=0
        \\end{{aligned}}
        $$




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

        answer_s = f"""
        see solution
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate
        pass


    def _problem_plane_through_a_point_and_parallel_to_2_vectors(self, *args, **kwargs):
        """
        Draw parallel vectors off the plane
        the plane and each parallel vector must be in different planes
        """
        v3d_helper = self.base_helper.get_vector_helper().get_vector_3d_helper()

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

        plt.ioff()
        plt.figure(figsize = (13, 6))
        origin = np.array([0, 0, 0])
        p1 = np.random.randint(-10, 10, size = 3)

        p1 = np.array([3, 3, 15])
        p2 = np.array([9, 2, 15])
        p3 = np.array([6, 8, 15])

        r_1 = p2 - p1
        r_2 = p3 - p1
        n = np.cross(r_1, r_2)
        rescale = 0.3
        n_rescale = rescale * np.cross(r_1, r_2)

        d = -(n[0]*p1[0] + n[1]*p1[1] + n[2]*p1[2])

        fig = plt.figure(figsize = (6, 6))
        ax = fig.add_subplot(projection='3d', box_aspect = (1, 1, 1))
        ax.quiver(*origin, *p1, label = r'$\vec{r_0}$', color = 'purple', arrow_length_ratio = 0.07)
        v3d_helper.plot_plane(n, p1 = p1, ax = ax)

        ax.plot(*p1, marker = 'o', color = 'blue')
        ax.quiver(*p1, *n_rescale, label = r'$\vec{n}$', color = 'green', arrow_length_ratio = 0.1)
        ax.quiver(*p1, *r_1, label = r'$\vec{r_1}$', color = 'lightgreen', arrow_length_ratio = 0.1)
        ax.quiver(*p1, *r_2, label = r'$\vec{r_2}$', color = 'cyan', arrow_length_ratio = 0.1)

        ax.legend()
        ax.set_axis_off()

        svgHelper = SvgHelper()
        svg_str = svgHelper.plt_to_svg()
        #plt.figure().clear()
        plt.clf()
        plt.close()

        prob_s = f"""
        Find the general equation of the plane that passes through the point ({p1[0]}, {p1[1]}, {p1[2]}) and is parallel to the two vectors ({r_1[0]}, {r_1[1]}, {r_1[2]}) and ({r_2[0]}, {r_2[1]}, {r_2[2]})
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')

        problemTemplate.add_solution(svg_str, 'text/svg')
        soln_stmts = []

        soln_stmt = f"""
        $\\vec{{n}}$ is the normal vector to plane
        $\\vec{{r}}$ is the vector of any arbitrary point
        $\\vec{{r_0}}$ is the vector of a given point
        $\\vec{{r_1}}$ is the parallel vector of the plane
        $\\vec{{r_2}}$ is the parallel vector of the plane

        """

        soln_stmts.append(soln_stmt.strip())

        soln_stmt = f"""
        The normal vector to the both parallel vectors can be compuated by cross product of the vectors as cross products are normal to each input vector.
        $$
        \\begin{{aligned}}
        \\vec{{n}} & =({r_1[0]}, {r_1[1]}, {r_1[2]}) \\times ({r_2[0]}, {r_2[1]}, {r_2[2]}) \\\\
        & =\\left|\\begin{{array}}{{ccc}}
        \\vec{{i}} & \\vec{{j}} & \\vec{{k}} \\\\
        {r_1[0]} & {r_1[1]} & {r_1[2]} \\\\
        {r_2[0]} & {r_2[1]} & {r_2[2]}
        \\end{{array}}\\right| \\\\
        & =\\left|\\begin{{array}}{{cc}}
        {r_1[1]} & {r_1[2]} \\\\
        {r_2[1]} & {r_2[2]}
        \\end{{array}}\\right| \\vec{{i}}-\\left|\\begin{{array}}{{cc}}
        {r_1[0]} & {r_1[2]}\\\\
        {r_2[0]} & {r_2[2]}
        \\end{{array}}\\right| \\vec{{j}}+\\left|\\begin{{array}}{{cc}}
        {r_1[0]} & {r_1[1]} \\\\
        {r_2[0]} & {r_2[1]}
        \\end{{array}}\\right| \\vec{{k}} \\\\
        & =({r_1[1]} \\times {r_2[2]} - {r_1[2]} \\times  {r_2[1]}) \\vec{{i}}-({r_1[0]} \\times{r_2[2]} - {r_2[0]} \\times{r_1[2]}) \\vec{{j}}+({r_1[0]} \\times {r_2[1]} -{r_2[0]} \\times{r_1[1]}) \\vec{{k}} \\\\
        & = {n[0]} \\vec{{i}}+ {n[1]} \\vec{{j}}+ {n[2]} \\vec{{k}} \\\\
        & =({n[0]}, {n[1]}, {n[2]}) .
        \\end{{aligned}}
        $$
        As the plane is parallel to both vector the above normal vector will also be normal to the plane.
        """
        soln_stmts.append(soln_stmt.strip())

        soln_stmt = f"""
        If r is an aribitray and r_0 another point on plane (r - r_0) will be a vector in the plane and will be normal to the normal vector n. Therefore, the plane can be expressed as:
        $$
        \\begin{{aligned}}
        & \\left(\\vec{{r}}-\\vec{{r}}_0\\right) \\cdot \\vec{{n}}=0 \\\\
        & \\implies\\left(x-{p1[0]}, y-{p1[1]}, z-{p1[2]}\\right) \\cdot({n[0]}, {n[1]}, {n[2]})=0 \\\\
        & \\implies {n[0]}\\left(x-{p1[0]}\\right)+{n[1]}\\left(y-{p1[1]}\\right)+{n[2]}\\left(z-{p1[2]}\\right)=0 \\\\
        & \\implies {n[0]} x + {n[1]} y + {n[2]} z + {d}=0
        \\end{{aligned}}
        $$


        """
        soln_stmts.append(soln_stmt.strip())

        soln_stmt = f"""

        """
        soln_stmts.append(soln_stmt.strip())

        soln_s = '\n\n'.join(soln_stmts)
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        see solution
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate
        pass


    def _problem_plane_through_3_points(self, *args, **kwargs):
        v3d_helper = self.base_helper.get_vector_helper().get_vector_3d_helper()

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

        plt.ioff()
        plt.figure(figsize = (13, 6))
        origin = np.array([0, 0, 0])
        # p1 = np.random.randint(-10, 10, size = 3)
        # p2 = np.random.randint(-10, 10, size = 3)
        # p3 = np.random.randint(-10, 10, size = 3)

        p1 = np.array([3, 3, 9])
        p2 = np.array([9, 2, 9])
        p3 = np.array([6, 8, 9])

        r_1 = p2 - p1
        r_2 = p3 - p1

        from sympy import Matrix, symbols, latex
        x, y, z = symbols('x, y, z')
        det_matrix = Matrix([
        [p1[0], p2[0], p3[0], x],
        [p1[1], p2[1], p3[1], y],
        [p1[2], p2[2], p3[2], z],
        [1, 1, 1, 1],
        ])
        det = det_matrix.det()
        rescale = 0.3
        n_rescale = rescale * np.cross(r_1, r_2)
        n = np.cross(r_1, r_2)
        d = -(n[0]*p1[0] + n[1]*p1[1] + n[2]*p1[2])

        v3d_helper.plot_plane(n, p1 = p1, xrange = [0, 10], yrange = [0, 10])

        ax = plt.gca()
        ax.plot(*p1, marker = 'o', color = 'blue')
        ax.text(p1[0] + 0.25, p1[1] + 0.25, p1[2] + 0.25, s = '$P_1$', fontsize = 12)

        ax.plot(*p2, marker = 'o', color = 'blue')
        ax.text(p2[0] + 0.25, p2[1] + 0.25, p2[2] + 0.25, s = '$P_2$', fontsize = 12)

        ax.plot(*p3, marker = 'o', color = 'blue')
        ax.text(p3[0] + 0.25, p3[1] + 0.25, p3[2] + 0.25, s = '$P_3$', fontsize = 12)

        ax.quiver(*p1, *n_rescale, label = r'$\vec{n}$', color = 'green')
        ax.quiver(*origin, *p1, label = r'$\vec{r_0}$', color = 'purple')
        ax.quiver(*p1, *r_1, label = r'$\vec{r_1}$', color = 'lightgreen')
        ax.quiver(*p1, *r_2, label = r'$\vec{r_2}$', color = 'cyan')

        ax.legend()


        ax.set_axis_off()
        ax.set_xlim(0, 10)
        ax.set_ylim(0, 10)
        ax.set_zlim(0, max(n))

        svgHelper = SvgHelper()
        svg_str = svgHelper.plt_to_svg()
        #plt.figure().clear()
        plt.clf()
        plt.close()

        prob_s = f"""
        Find the general equation of the plane that passes through the points ({p1[0]}, {p1[1]}, {p1[2]}), ({p2[0]}, {p2[1]}, {p2[2]}) and ({p3[0]}, {p3[1]}, {p3[2]})
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')

        problemTemplate.add_solution(svg_str, 'text/svg')
        soln_stmts = []
        soln_stmt = f"""
        <h2>Method 1:</h2>
        The volume of tetrahedron formed by 4 non co-linear points on the plane will be 0.
        $P_1 = ({p1[0]}, {p1[1]}, {p1[2]})$
        $P_2 = ({p2[0]}, {p2[1]}, {p2[2]})$
        $P_3 = ({p3[0]}, {p3[1]}, {p3[2]})$
        $P = (x, y, z)$

        $$
        V=\\frac{{1}}{{6}}\\text{{det}}\\left(\\left|\\begin{{array}}{{cccc}}
        {p1[0]} & {p2[0]} & {p3[0]} & x \\\\
        {p1[1]} & {p2[1]} & {p3[1]} & y \\\\
        {p1[2]} & {p2[2]} & {p3[2]} & z \\\\
        1 & 1 & 1 & 1
        \\end{{array}}\\right|\\right)=0
        $$
        $$
        \\begin{{aligned}}
        &\\frac{{1}}{{6}} \\left({latex(det)}\\right) = 0 \\\\
        \Rightarrow &\\left({latex(det)}\\right) = 0 \\\\
        \Rightarrow &\\left({latex(-det)}\\right) = 0
        \\end{{aligned}}
        $$
        """
        soln_stmts.append(soln_stmt.strip())

        soln_stmt = f"""
        <h2>Method 2:</h2>
        $\\vec{{n}}$ is the normal vector to plane
        $\\vec{{r}}$ is the vector of any arbitrary point
        $\\vec{{r_0}}$ is the vector of a given point
        $\\vec{{r_1}}$ is the parallel vector of the plane
        $\\vec{{r_2}}$ is the parallel vector of the plane

        $P_1 = ({p1[0]}, {p1[1]}, {p1[2]})$
        $P_2 = ({p2[0]}, {p2[1]}, {p2[2]})$
        $P_3 = ({p3[0]}, {p3[1]}, {p3[2]})$
        We can derive 2 vectors in the plane and normal vector to them.
        $$
        \\begin{{aligned}}
        \\vec{{r_1}} & = P_2 - P_1 \\\\
        \\vec{{r_1}} & =({p2[0]}, {p2[1]}, {p2[2]}) - ({p1[0]}, {p1[1]}, {p1[2]}) \\\\
        \\vec{{r_1}} & = ({r_1[0]}, {r_1[1]}, {r_1[2]})
        \\end{{aligned}}
        $$

        $$
        \\begin{{aligned}}
        \\vec{{r_2}} & = P_3 - P_1 \\\\
        \\vec{{r_2}} & =({p3[0]}, {p3[1]}, {p3[2]}) - ({p1[0]}, {p1[1]}, {p1[2]}) \\\\
        \\vec{{r_2}} & = ({r_2[0]}, {r_2[1]}, {r_2[2]})
        \\end{{aligned}}
        $$

        """
        soln_stmts.append(soln_stmt.strip())

        soln_stmt = f"""
        The normal vector to the both parallel vectors can be compuated by cross product of the vectors as cross products are normal to each input vector.
        $$
        \\begin{{aligned}}
        \\vec{{n}} & =({r_1[0]}, {r_1[1]}, {r_1[2]}) \\times ({r_2[0]}, {r_2[1]}, {r_2[2]}) \\\\
        & =\\left|\\begin{{array}}{{ccc}}
        \\vec{{i}} & \\vec{{j}} & \\vec{{k}} \\\\
        {r_1[0]} & {r_1[1]} & {r_1[2]} \\\\
        {r_2[0]} & {r_2[1]} & {r_2[2]}
        \\end{{array}}\\right| \\\\
        & =\\left|\\begin{{array}}{{cc}}
        {r_1[1]} & {r_1[2]} \\\\
        {r_2[1]} & {r_2[2]}
        \\end{{array}}\\right| \\vec{{i}}-\\left|\\begin{{array}}{{cc}}
        {r_1[0]} & {r_1[2]}\\\\
        {r_2[0]} & {r_2[2]}
        \\end{{array}}\\right| \\vec{{j}}+\\left|\\begin{{array}}{{cc}}
        {r_1[0]} & {r_1[1]} \\\\
        {r_2[0]} & {r_2[1]}
        \\end{{array}}\\right| \\vec{{k}} \\\\
        & =({r_1[1]} \\times {r_2[2]} - {r_1[2]} \\times  {r_2[1]}) \\vec{{i}}-({r_1[0]} \\times{r_2[2]} - {r_2[0]} \\times{r_1[2]}) \\vec{{j}}+({r_1[0]} \\times {r_2[1]} -{r_2[0]} \\times{r_1[1]}) \\vec{{k}} \\\\
        & = {n[0]} \\vec{{i}}+ {n[1]} \\vec{{j}}+ {n[2]} \\vec{{k}} \\\\
        & =({n[0]}, {n[1]}, {n[2]}) .
        \\end{{aligned}}
        $$
        As the normal vector will be normal to the plane also we can use that property to derive the equation of the plane

        """
        soln_stmts.append(soln_stmt.strip())
        soln_stmt = f"""
        If $\\vec{{r}}$ is an aribitray and $\\vec{{r_0}}$ another point on plane $(\\vec{{r}} - \\vec{{r_0}})$ will be a vector in the plane and will be normal to the normal vector $\\vec{{n}}$. Therefore, the plane can be expressed as:
        $$
        \\begin{{aligned}}
        & \\left(\\vec{{r}}-\\vec{{r}}_0\\right) \\cdot \\vec{{n}}=0 \\\\
        & \\implies\\left(x-{p1[0]}, y-{p1[1]}, z-{p1[2]}\\right) \\cdot({n[0]}, {n[1]}, {n[2]})=0 \\\\
        & \\implies {n[0]}\\left(x-{p1[0]}\\right)+{n[1]}\\left(y-{p1[1]}\\right)+{n[2]}\\left(z-{p1[2]}\\right)=0 \\\\
        & \\implies {n[0]} x + {n[1]} y + {n[2]} z + {d}=0
        \\end{{aligned}}
        $$

        """
        soln_stmts.append(soln_stmt.strip())
        soln_s = '\n\n'.join(soln_stmts)
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        see solution
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate
        pass

    def _problem_plane_through_2_lines(self, *args, **kwargs):
        v3d_helper = self.base_helper.get_vector_helper().get_vector_3d_helper()

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

        plt.ioff()
        plt.figure(figsize = (13, 6))
        origin = np.array([0, 0, 0])

        p1 = np.array([3, 3, 15])
        p2 = np.array([9, 2, 15])

        r_1 = np.array([6, -1, 0])
        r_2 = np.array([3, 5, 0])
        n = np.cross(r_1, r_2)

        rescale = 0.3
        n = np.cross(r_1, r_2)
        n_rescale = rescale * n
        d = -(n[0]*p1[0] + n[1]*p1[1] + n[2]*p1[2])

        fig = plt.figure(figsize = (6, 6))
        ax = fig.add_subplot(projection='3d', box_aspect = (1, 1, 1))
        v3d_helper.plot_plane(n, p1 = p1, xrange = [0, 10], yrange = [0, 10], ax = ax)

        ax = plt.gca()
        ax.plot(*p1, marker = 'o', color = 'blue')
        ax.text(p1[0] + 0.25, p1[1] + 0.25, p1[2] + 0.25, s = '$P_1$', fontsize = 12)

        ax.plot(*p2, marker = 'o', color = 'blue')
        ax.text(p2[0] + 0.25, p2[1] + 0.25, p2[2] + 0.25, s = '$P_2$', fontsize = 12)


        ax.quiver(*p1, *n_rescale, label = r'$\vec{n}$', color = 'green')
        ax.quiver(*origin, *p1, label = r'$\vec{r_0}$', color = 'purple')
        v3d_helper.plot_line(p1 = p1, n = r_1, t_range = [-3, 3], ax = ax)
        v3d_helper.plot_line(p1 = p2, n = r_2, t_range = [-3, 3], ax = ax)

        ax.legend()


        ax.set_axis_off()
        ax.set_xlim(0, 10)
        ax.set_ylim(0, 10)
        ax.set_zlim(0, max(n))

        svgHelper = SvgHelper()
        svg_str = svgHelper.plt_to_svg()
        #plt.figure().clear()
        plt.clf()
        plt.close()

        prob_s = f"""
        Find the vector form of the equation of the plane containing the two straight lines
        $\\vec{{r_1}} = ({p1[0]}, {p1[1]}, {p1[2]}) + t_1 ({r_1[0]}, {r_1[1]}, {r_1[2]})$
        $\\vec{{r_2}} = ({p2[0]}, {p2[1]}, {p2[2]}) + t_1 ({r_2[0]}, {r_2[1]}, {r_2[2]})$

        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')

        problemTemplate.add_solution(svg_str, 'text/svg')
        soln_s = f"""

        $\\vec{{n}}$ is the normal vector to plane
        $\\vec{{r}}$ is the vector of any arbitrary point
        $\\vec{{r_0}}$ is the vector of a given point
        $\\vec{{r_1}}$ is the line on the plane
        $\\vec{{r_2}}$ is the line on the plane

        $\\vec{{r_1}} = ({p1[0]}, {p1[1]}, {p1[2]}) + t_1 ({r_1[0]}, {r_1[1]}, {r_1[2]})$
        $\\vec{{r_2}} = ({p2[0]}, {p2[1]}, {p2[2]}) + t_2 ({r_2[0]}, {r_2[1]}, {r_2[2]})$


        The normal vector to the both parallel vectors can be compuated by cross product of the vectors as cross products are normal to each input vector.
        $$
        \\begin{{aligned}}
        \\vec{{n}} & =({r_1[0]}, {r_1[1]}, {r_1[2]}) \\times ({r_2[0]}, {r_2[1]}, {r_2[2]}) \\\\
        & =\\left|\\begin{{array}}{{ccc}}
        \\vec{{i}} & \\vec{{j}} & \\vec{{k}} \\\\
        {r_1[0]} & {r_1[1]} & {r_1[2]} \\\\
        {r_2[0]} & {r_2[1]} & {r_2[2]}
        \\end{{array}}\\right| \\\\
        & =\\left|\\begin{{array}}{{cc}}
        {r_1[1]} & {r_1[2]} \\\\
        {r_2[1]} & {r_2[2]}
        \\end{{array}}\\right| \\vec{{i}}-\\left|\\begin{{array}}{{cc}}
        {r_1[0]} & {r_1[2]}\\\\
        {r_2[0]} & {r_2[2]}
        \\end{{array}}\\right| \\vec{{j}}+\\left|\\begin{{array}}{{cc}}
        {r_1[0]} & {r_1[1]} \\\\
        {r_2[0]} & {r_2[1]}
        \\end{{array}}\\right| \\vec{{k}} \\\\
        & =({r_1[1]} \\times {r_2[2]} - {r_1[2]} \\times  {r_2[1]}) \\vec{{i}}-({r_1[0]} \\times{r_2[2]} - {r_2[0]} \\times{r_1[2]}) \\vec{{j}}+({r_1[0]} \\times {r_2[1]} -{r_2[0]} \\times{r_1[1]}) \\vec{{k}} \\\\
        & = {n[0]} \\vec{{i}}+ {n[1]} \\vec{{j}}+ {n[2]} \\vec{{k}} \\\\
        & =({n[0]}, {n[1]}, {n[2]}) .
        \\end{{aligned}}
        $$
        As the normal vector will be normal to the plane also we can use that property to derive the equation of the plane

        A point on plane is ({p1[0]}, {p1[1]}, {p1[2]})

        If $\\vec{{r}}$ is an aribitray and $\\vec{{r_0}}$ another point on plane $(\\vec{{r}} - \\vec{{r_0}})$ will be a vector in the plane and will be normal to the normal vector $\\vec{{n}}$. Therefore, the plane can be expressed as:
        $$
        \\begin{{aligned}}
        & \\left(\\vec{{r}}-\\vec{{r}}_0\\right) \\cdot \\vec{{n}}=0 \\\\
        & \\implies\\left(x-{p1[0]}, y-{p1[1]}, z-{p1[2]}\\right) \\cdot({n[0]}, {n[1]}, {n[2]})=0 \\\\
        & \\implies {n[0]}\\left(x-{p1[0]}\\right)+{n[1]}\\left(y-{p1[1]}\\right)+{n[2]}\\left(z-{p1[2]}\\right)=0 \\\\
        & \\implies {n[0]} x + {n[1]} y + {n[2]} z + {d}=0
        \\end{{aligned}}
        $$



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

        answer_s = f"""
        see solution
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate
        pass

