from .no_distort import gds_no_distort_transform
from .special import gds_special_no_distort_transform
from .. import transformable
from ..coord import coord2, coord2_property
from ...mixin import mixin
from ... import constants

import math
import copy 

__all__ = ["gds_translation"]

class gds_translation(gds_special_no_distort_transform):
    """ translation transform """
    def __init__(self, translation = (0.0, 0.0), **kwargs):
        super(gds_translation, self).__init__(
            translation = translation,
            **kwargs)

    translation = getattr(gds_no_distort_transform, 'translation')

    # overloading for efficiency
    def apply_to_coord(self, coord):  
        """ apply transformation to coordinate """
        return self.__translate__(coord)

    def reverse_on_coord(self, coord):      
        """ apply reverse transformation on coodinate """
        return self.__inv_translate__(coord)

    def apply_to_array(self, coords):      
        """ applies transformation to numpy array """
        return self.__translate_array__(coords)

    def reverse_on_array(self, coords):      
        """ apply reverse transformation to numpy array """
        return self.__inv_translate_array__(coords)

    def __add__(self, other):
        """ returns the concatenation of this transform and other """
        if other == None: return copy.deepcopy(self)
        if isinstance(other, gds_translation):
            return gds_translation(coord2(self.translation.x + other.translation.x, self.translation[1] + other.translation[1]))
        else:
            return gds_special_no_distort_transform.__add__(self, other)
    
    def __iadd__(self, other):
        """ concatenates other to this transform """        
        if other == None: return self
        if isinstance(other, gds_translation):
            self.translation = coord2(self.translation.x + other.translation.x, self.translation.y + other.translation.y)
            return self
        else:
            return gds_no_distort_transform.__iadd__(self, other)

    def __neg__(self):
        """ returns the reverse transformation """
        return gds_translation(coord2(-self.translation.x, -self.translation.y))

    def is_identity(self):
        """ returns True if the transformation does nothing """
        return ((self.translation.x == 0.0) and
                (self.translation.y == 0.0) 
            )


def shape_translate(shape, translation_vector = (1.0,0.0)):
    """ legacy: apply a translation to a shape """
    return gds_translation(translation_vector)(shape)

class __translation___mixin__(object):
    def move(self, position):
        """moves this object """
        return self.transform(gds_translation(position))

    def move_copy(self, position):
        """moves copy of this object """
        return self.transform_copy(gds_translation(position))
    def move_polar(self, distance, angle):
        return self.move((distance * math.cos(constants.DEG2RAD * angle), distance * math.sin(constants.DEG2RAD * angle))) 
    def move_polar_copy(self, distance, angle):
        """moves copy of this object """
        return self.move_copy((distance * math.cos(constants.DEG2RAD * angle), distance * math.sin(constants.DEG2RAD * angle))) 

    def translate(self, translation = (0.0, 0.0)):
        """translates this object """
        return self.transform(gds_translation(translation))
    def translate_copy(self, position):
        """moves copy of this object """
        return self.transform_copy(gds_translation(position))


mixin.mixin(transformable.gds_transformable_basic, __translation___mixin__)
