from copy import deepcopy
import gk_global
import math

       
class gds_transformable_basic(object):
    def transform(self, transformation):
        """applies transform to this object """
        pass

    def transform_copy(self, transformation):
        """ applies a transformation on a copy of this object """
        T = deepcopy(self)
        T.transform(transformation) # make a copy
        return T
    
    def reverse_transform(self,transformation):
        """applies reversed transform this object """
        return self.transform(-transformation)
    
    def reverse_transform_copy(self,transformation):
        """applies transform to copy of this object """
        T = deepcopy(self)
        T.reverse_transform(transformation) # make a copy
        return T

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

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

    def translate(self, translation = (0.0, 0.0)):
        """translates this object """
        return self.transform(gk_transforms.gds_translation(translation))
    def rotate(self, rotation_center = (0.0, 0.0), rotation = 0.0, absolute_rotation = False):
        """rotates this object """
        return self.transform(gk_transforms.gds_rotation(rotation_center, rotation, absolute_rotation))
    def magnify(self, magnification_center = (0.0, 0.0), magnification = 1.0 , absolute_magnification = False):
        """magnifies this object """
        return self.transform(gk_transforms.gds_magnification(magnification_center, magnification, absolute_magnification))
    def h_mirror(self, mirror_plane_x = 0.0):
        """mirrors this object horizontally """
        return self.transform(gk_transforms.gds_h_mirror(mirror_plane_x))
    def v_mirror(self, mirror_plane_y = 0.0):
        """mirrors this this object vertically"""
        return self.transform(gk_transforms.gds_v_mirror(mirror_plane_y))
    def c_mirror(self, mirror_center = (0.0, 0.0)):
        """point-mirrors this object """
        return self.transform(gk_transforms.gds_c_mirror(mirror_center))
        
    def translate_copy(self, translation = (0.0, 0.0)):
        """translates a copy of this object """
        return self.transform_copy(gk_transforms.gds_translation(translation))
    def rotate_copy(self, rotation_center = (0.0, 0.0), rotation = 0.0, absolute_rotation = False):
        """rotates a copy of this object """
        return self.transform_copy(gk_transforms.gds_rotation(rotation_center, rotation, absolute_rotation))
    def magnify_copy(self, magnification_center = (0.0, 0.0), magnification = 1.0 , absolute_magnification = False):
        """magnifies a copy of this object """
        return self.transform_copy(gk_transforms.gds_magnification(magnification_center, magnification, absolute_magnification))
    def h_mirror_copy(self, mirror_plane_x = 0.0):
        """mirrors a copy of this object horizontally """
        return self.transform_copy(gk_transforms.gds_h_mirror(mirror_plane_x))
    def v_mirror_copy(self, mirror_plane_y = 0.0):
        """mirrors a copy of this object vertically """
        return self.transform_copy(gk_transforms.gds_v_mirror(mirror_plane_y))
    def c_mirror_copy(self, mirror_center = (0.0, 0.0)):
        """point_mirrors copy of this object """
        return self.transform_copy(gk_transforms.gds_c_mirror(mirror_center))

class gds_no_distort_transformable(gds_transformable_basic):
    """ object that cannot be distorted """
    pass

class gds_transformable(gds_transformable_basic):
    """ object that can be transformed """
    pass

import gk_transforms

class gds_stored_transformable(gds_transformable):
    """ transformable that stores its transforms """
    __transformation_type__ = gk_transforms.gds_transform
    transformation = gk_transforms.transformation_property("__transformation")
    def __init__(self, transformation = None):
        self.transformation = transformation
    
    
    
    #def get_transformation(self): return self.__transformation
    #def set_transformation(self, transformation):
        #if transformation == None:
            #self.__transformation = gk_transforms.gds_identity_transform()
            #return self
        #if isinstance(transformation, self.__transformation_type__):
            #self.__transformation = transformation
        #else:
            #raise TypeError("Wrong type " + str(type(transformation)) + " for transformation in gds_stored_transformable")
        #return self
    #transformation = property(get_transformation, set_transformation)
    #""" transformations already applied on the object """
    
    def transform(self, transformation):
        """ applies a transformation on this object """
        if isinstance(transformation, self.__transformation_type__):
            self.transformation = self.transformation + transformation # make a copy
        else:
            raise TypeError("Wrong type " + str(type(transformation)) + " for transformation in gds_stored_transformable")
        return self

    
    def expand_transform(self):
        """ tries to propagate the transformation as deep as possible in the hierarchy """

        return self

class gds_stored_no_distort_transformable(gds_stored_transformable, gds_no_distort_transformable):
    """ transformable that stores its homothetic transforms """
    __transformation_type__ = gk_transforms.gds_no_distort_transform
    transformation= gk_transforms.no_distort_transformation_property("__transformation")