import region as rr
from numpy import empty
from .region_utils import *

class Shape(object):

    __precise_string = "{:.12g}"  # Format string for double values when printed

    def __init__(self, shape_ptr):
        self.__clear__()

        (inc_flag, self._name) = rr.regShapeGetName(shape_ptr)
        self._name =  self._name.lower()

        if inc_flag == 1:
            self._include = incINCLUDE
        else:
            self._include = incEXCLUDE

        self._component = rr.regShapeGetComponent(shape_ptr)

        if (self._name == str("field")):
            return

        (self._xpoints, self._ypoints) = rr.regShapeGetPoints(shape_ptr)
        if self._xpoints is not None:
            self._xpoints.flags.writeable = False

        if self._ypoints is not None:
            self._ypoints.flags.writeable = False

        self._radii = rr.regShapeGetRadii(shape_ptr)
        if self._radii is not None:
            self._radii.flags.writeable = False

        self._angles = rr.regShapeGetAngles(shape_ptr)
        if self._angles is not None:
            self._angles.flags.writeable = False


    def __clear__(self):
        self._include = 0
        self._name = ""
        self._xpoints = None
        self._ypoints = None
        self._radii = None
        self._angles = None
        self._component = 0
        self.logic = None

    @property
    def name(self):
        """Get the shape name"""
        return self._name


    @property
    def xpoints(self):
        """Get the X values for the shape"""
        return self._xpoints

    
    @property
    def ypoints(self):
        """Get the Y values for the shape"""
        return self._ypoints

        
    @property
    def radii(self):
        """Get the radii of the shape"""
        return self._radii


    @property
    def angles(self):
        """Get the angle of the shape"""
        return self._angles

    @property
    def component(self):
        """Get the component of the shape"""
        return self._component


    @property
    def include(self):
        """Get the include flag"""
        return self._include


    def _format_string(self, fmt_str):
        """
        Convert the values to strings using the desired precision/format
        """

        # convert decimal arrays to list of formatted strings

        xx_str = []
        if (self.xpoints is not None):
            xx_str = [ self.__precise_string.format(x) for x in self.xpoints ]

        yy_str = []
        if (self.ypoints is not None):
            yy_str = [ self.__precise_string.format(y) for y in self.ypoints ]

        rad_str = []
        if (self.radii is not None):
            rad_str = [ self.__precise_string.format(r) for r in self.radii ]

        ang_str = []
        if (self.angles is not None):
            ang_str = [ self.__precise_string.format(a) for a in self.angles ]        

        fmt_vals = {
            'x0' : xx_str[0] if len(xx_str) > 0 else None,
            'x1' : xx_str[1] if len(xx_str) > 1 else None,
            'y0' : yy_str[0] if len(yy_str) > 0 else None,
            'y1' : yy_str[1] if len(yy_str) > 1 else None,
            'r0' : rad_str[0] if len(rad_str) > 0 else None,
            'r1' : rad_str[1] if len(rad_str) > 1 else None,
            'a0' : ang_str[0] if len(ang_str) > 0 else None,
            'a1' : ang_str[1] if len(ang_str) > 1 else None,
            'i'  : self._include.str,
            'n'  : self.name,
            'xy' : ",".join([ "{},{}".format(x,y) for x,y in zip( xx_str, yy_str ) ])
            }
            
        return fmt_str.format( **fmt_vals )



    def __str__(self):
        raise NotImplementedError("Implement this in the derived classes")



class Annulus(Shape):
    """An annulus is defined by x_center, y_center, inner_radius, outer_radius"""

    _nangles = 0
    _nradii = 2

    def __str__( self ):
        return self._format_string("{i}{n}({x0},{y0},{r0},{r1})")


class Box(Shape):
    """A box is defined by x_center, y_center, x_length, y_length"""

    _nangles = 0
    _nradii = 2
    
    def __str__( self ):
        if self.name == "rotbox":
            return self._format_string("{i} {n}({x0},{y0},{r0},{r1},{a0})")

        return self._format_string("{i}{n}({x0},{y0},{r0},{r1})")


class Circle(Shape):
    """A circle is defined by x_center, y_center, radius"""

    _nangles = 0
    _nradii = 1

    def __str__( self ):
        return self._format_string("{i}{n}({x0},{y0},{r0})")


class Ellipse(Shape):
    """An ellipse is defined by x_center, y_center, major_axis, minor_axis, and angle"""

    _nangles = 1
    _nradii = 2

    def __str__( self ):
        return self._format_string("{i}{n}({x0},{y0},{r0},{r1},{a0})")
        

class Field(Shape):
    """A field is defined to be the entire R^2 dataspace"""

    _nangles = 0
    _nradii = 0

    def __str__( self ):
        return self._format_string("{i}{n}()")


class Pie(Shape):
    """A Pie is defined by x_center, y_center, inner_radius, outer_radius, start_angle, stop_angle"""

    _nangles = 2
    _nradii = 2

    def __str__( self ):
        return self._format_string("{i}{n}({x0},{y0},{r0},{r1},{a0},{a1})")
        

class Point(Shape):
    """A point is defined by x_center, y_center"""

    _nangles = 0
    _nradii = 0
    
    def __str__( self ):
        return self._format_string("{i}{n}({x0},{y0})")


class Polygon(Shape):
    """A Polygon is defined as x1, y1, x2, y2, x3, y3,..."""

    _nangles = 0
    _nradii = 0

    def __str__( self ):
        return self._format_string("{i}{n}({xy})")


class Rectangle(Shape):
    """A Rectangle is defined as lower_left_x, lower_left_y, upper_right_x, upper_right_y"""

    _nangles = 0
    _nradii = 0

    def __str__( self ):
        #if self.name == 'rotrectangle':
        #    return self._format_string("{i}{n}({x0},{y0},{x1},{y1},{a0})")

        return self._format_string("{i}{n}({x0},{y0},{x1},{y1})")


class Rotbox(Shape):
    """A Rotbox is defined as x_center, y_center, x_length, y_length, angle """

    _nangles = 1
    _nradii = 2

    def __str__(self):
        return self._format_string("{i}{n}({x0},{y0},{r0},{r1},{a0})")


#class Rotrectangle(Shape):
#    """A Rotrectangle is defined as lower_left_x, lower_left_y, upper_right_x, upper_right_y, angle """

#    _nangles = 1
#    _nradii = 0

#    def __str__(self):
#        return self._format_string("{i}{n}({x0},{y0},{x1},{y1},{a0})")


class Sector(Shape):
    """A Sector is defined by x_center, y_center, start_angle, stop_angle"""

    _nangles = 2
    _nradii = 0

    def __str__( self ):
        return self._format_string("{i}{n}({x0},{y0},{a0},{a1})")

