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 ...properties.descriptor import restricted_set_function_property
from ...properties.processors import processor_typecast
from ...properties.restrictions import restrict_type
from ...properties.initializer import SUPPRESSED


__all__ = ["gds_magnification"]


class gds_magnification(gds_special_no_distort_transform):
    """ scaling transformation with respect to a given point """
    def __init__(self, magnification_center = (0.0, 0.0), magnification = 1.0, absolute_magnification = False, **kwargs):
        if not kwargs.has_key('translation'): kwargs['translation'] = SUPPRESSED
        super(gds_magnification, self).__init__(
            magnification_center = magnification_center,
            magnification = magnification,
            absolute_magnification = absolute_magnification,
            **kwargs)
        

    absolute_magnification = getattr(gds_no_distort_transform, 'absolute_magnification')

    
    def set_magnification (self, value):
        
        self.__magnification__ = value
        if hasattr(self, "__magnification_center__"):
            center = self.__magnification_center__
            self.translation = coord2((1 - self.__magnification__) * center.x,
                                          (1 - self.__magnification__) * center.y )
            
            
    magnification = restricted_set_function_property("__magnification__", set_magnification, default = 1.0)
    
    
    def set_magnification_center(self, center):
        if not isinstance(center, coord2):
            center = coord2(center[0], center[1])
        self.__magnification_center__ = center
        if hasattr(self, "__magnification__"):
            self.translation = coord2((1 - self.__magnification__) * center.x,
                                          (1 - self.__magnification__) * center.y )
    magnification_center = restricted_set_function_property("__magnification_center__", set_magnification_center, restriction = restrict_type(coord2), preprocess = processor_typecast(coord2), default = (0.0, 0.0))
    
    # overloading for efficiency
    def apply_to_coord(self, coord):      
        """ apply transformation to coordinate """
        coord = self.__magnify__(coord)
        coord = self.__translate__(coord)
        return coord

    def reverse_on_coord(self, coord):      
        """ apply reverse transformation to coordinate """
        coord = self.__inv_translate__(coord)
        coord = self.__inv_magnify__(coord)
        return coord

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

    def reverse_on_array(self, coords):      
        """ internal use: applies reverse transformation to a numpy array """
        coords = self.__inv_translate_array__(coords)
        coords = self.__inv_magnify__array__(coords)
        return coords

    def apply_to_length(self, length):
        """ applies transformation to a distance """
        return length * self.magnification
    def reverse_on_length(self, length):
        """ applies reverse transformation to a distance """
        return length / self.magnification

    def __neg__(self):
        """ returns reverse transformation """
        return gds_magnification(self.magnification_center, 1.0/self.magnification)

    def is_identity(self):
        """ returns True if the transformation does nothing """
        return (self.magnification == 1.0)

    def is_isometric(self):
        """ returns True if the transformation does nothing """
        return (self.magnification == 1.0)



class __magnification___mixin__(object):
    def magnify(self, magnification_center = (0.0, 0.0), magnification = 1.0 , absolute_magnification = False):
        """magnifies this object """
        return self.transform(gds_magnification(magnification_center, magnification, absolute_magnification))
    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(gds_magnification(magnification_center, magnification, absolute_magnification))


mixin.mixin(transformable.gds_transformable_basic, __magnification___mixin__)