import numpy as np 
from AbstractPointField import AbstractPointFieldClass
import scipy.constants as const

class PointElectricFieldClass(AbstractPointFieldClass):
    """ Class that generates an electric field originating from a point particle

        Class Attributes:
            sourceParticle (object: Particle): The source particle that generates the
                electric field
            name (string): Name of the point source electric field
    """

    def __init__(self, sourceParticle, name='Electric Point Field'):
        """ Constructor for the PointElectricFieldClass class
                Inherits the __init__ from AbstractPointFieldClass
            
            Args:
                sourceParticle (object: Particle): The source particle that generates the
                    electric field
                name (string): Name of the point source electric field
        """
        super().__init__(sourceParticle=sourceParticle
        , name=name)

    def __repr__(self):
        return 'Electric Point Field: {0}, Source Particle of Electric Field: {1}'.format(
            self.name, self.sourceParticle)
    
    def GenerateField(self, affectedParticle):
        """ Method that returns the electric field generated by the source particle
                that affects the affectedParticle.
            
            Args:
                affectedParticle (object: Particle): The particle being affected by the
                    electric field
            
            Parameters:
                displacement (ndarray): The vector that represents the position of 
                    the source particle subtracted from the position of the affected particle.
                distance (float): The norm of the displacement between the two particles
            
            Returns:
                Electric Field (ndarray): The electric field that acts on the affectedParticle
                    , originating from the sourceParticle.
        """
        displacement = affectedParticle.position - self.sourceParticle.position
        distance = np.linalg.norm(displacement)
        
        return (self.sourceParticle.charge * displacement / (4 * const.pi * const.epsilon_0  
        * distance * distance * distance))