from copy import deepcopy
from . import transform
import math

__all__ = ["gds_transformable",
           "gds_no_distort_transformable",
           "gds_stored_transformable",
           "gds_stored_no_distort_transformable"]

class __gds_transformable(object):
    pass

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

    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

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

from . import transforms

class gds_stored_transformable(gds_transformable):
    """ transformable that stores its transforms """
    __transformation_type__ = transform.gds_transform
    transformation = transform.generic_transformation_property()
    def __init__(self, transformation = None, **kwargs):
        kwargs['transformation'] = transformation
        super(gds_stored_transformable, self).__init__(**kwargs)
    
    
    
    #def get_transformation(self): return self.__transformation
    #def set_transformation(self, transformation):
        #if transformation == None:
            #self.__transformation = 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
        elif transformation == None:
            return
        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__ = transform.gds_generic_no_distort_transform
    transformation= transform.transformation_property()