# -*- coding: utf-8 -*-
#
# File: gvsig.py
#
# Copyright (c) 2011 by Model Driven Development sl and Antonio Carrasco Valero
#
# GNU General Public License (GPL)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
#
#

"""
Utility functions to manage gvSIG geometries
"""

__author__ = """Antonio Carrasco Valero
Model Driven Development sl and Antonio Carrasco Valero
<carrasco@modeldd.org>
Victor Acevedo Royer <vacevedo@gvsig.com> <vacevedor@gmail.com>
"""

__docformat__ = 'plaintext'


from org.gvsig.fmap.geom import Geometry, GeometryLocator
from org.gvsig.fmap.geom.primitive import Point
from org.gvsig.tools import ToolsLocator


#GeometryTypes
AGGREGATE = Geometry.TYPES.AGGREGATE
ARC = Geometry.TYPES.ARC
CIRCLE = Geometry.TYPES.CIRCLE
CURVE = Geometry.TYPES.CURVE
ELLIPSE = Geometry.TYPES.ELLIPSE
ELLIPTICARC = Geometry.TYPES.ELLIPTICARC
GEOMETRY = Geometry.TYPES.GEOMETRY
MULTICURVE = Geometry.TYPES.MULTICURVE
MULTIPOINT = Geometry.TYPES.MULTIPOINT
MULTISOLID = Geometry.TYPES.MULTISOLID
MULTISURFACE = Geometry.TYPES.MULTISURFACE
NULL = Geometry.TYPES.NULL
POINT = Geometry.TYPES.POINT
SOLID =  Geometry.TYPES.SOLID
SPLINE = Geometry.TYPES.SPLINE
SURFACE = Geometry.TYPES.SURFACE

# Common named geometry types
POLYGON = Geometry.TYPES.SURFACE
LINE = Geometry.TYPES.CURVE
MULTILINE = Geometry.TYPES.MULTICURVE
MULTIPOLYGON = Geometry.TYPES.MULTISURFACE

# geometrySubTypes 
D2 = Geometry.SUBTYPES.GEOM2D
D2M = Geometry.SUBTYPES.GEOM2DM
D3 = Geometry.SUBTYPES.GEOM3D
D3M = Geometry.SUBTYPES.GEOM3DM
UNKNOWN = Geometry.SUBTYPES.UNKNOWN
 
def createGeometry(type, subtype=D2):
    """
    Returns a new geometry with a concrete type and subtype or None if can't 
    create geometry.
    :param type: geometry type
    :type type: string
    :param subtype: geometry subtype
    :type type: string
    :return: geometry
    :rtype: geometry
    """
    try:
        geometryManager = GeometryLocator.getGeometryManager()
        geometry = geometryManager.create(type, subtype)
    except:
        return None
    return geometry
  
def createPoint(x=0, y=0, subtype=D2):
    """
    Returns a new point with a subtype and sets the value for the X and the Y 
    coordinates (default 0,0) or None if can't create point
    :param x: X coordinate value 
    :param y: Y coordinate value
    :type x: double
    :type y: double
    :return: Point
    :rtype: Point      
    """
    try:
        geometryManager = GeometryLocator.getGeometryManager()
        point = geometryManager.createPoint(x, y, subtype)
    except:
        return None
        
    return point

def createMultiPoint(subtype=D2, points=None):
    """
    Returns a new multipoint with a subtype from a list of Points instances. 
    Also values of X and Y tuples like ([x1, y1], [x2, y2], ...., [xn, yn]) are 
    allowed. If not points returns empty multipoint geometry. If can't create 
    geometry return None.
    :param points: list of points
    :type points: list
    :return: multipoint
    :rtype: multipoint
    """
    multipoint = createGeometry(MULTIPOINT, subtype)
    if all(points, multipoint):
        try:
            for point in points: 
                multipoint.addPrimitive(point)
        except:
            return None
    
    return multipoint 

def createPolygon(subtype=D2, vertexes=None):  
    """
    Returns a new polygon with a subtype. Or None if can't create the geometry
    :return: polygon
    :rtype: Geometry    
    """  
    polygon = createGeometry(SURFACE, subtype)
    if all(vertexes, polygon):
        try:
            for vertex in vertexes:
                polygon.addPoint(vertex)
            polygon.closePrimitive()
        except:
            return None  
    return polygon

def createMultiPolygon(subtype=D2, polygons=None):  
    """
    Returns a new multipolygon with a subtype. or None if can't create geometry
    :return: multipolygon
    :rtype: Geometry
    """  
    multipolygon = createGeometry(MULTISURFACE, subtype)
    return multipolygon  
  
def createLine(subtype=D2, vertexes=None):  
    """
    Returns a new line with a subtype or None if can't create geometry
    :return: polygon
    :rtype: Geometry
    """  
    line = createGeometry(CURVE, subtype)
    return line

def createMultiLine(subtype=D2, lines = None):  
    """
    Create a new multiline with a subtype or None if can't create geometry
    :return: multiline
    :rtype: Geometry
    """  
    multiline = createGeometry(MULTILINE, subtype)
    return multiline
  
def createEnvelope(pointMax=None, pointMin=None, dimension=2):
    """
    Returns envelope as a minimum bounding box or rectangle. This envelope is 
    equivalent to the GM_Envelope specified in ISO 19107. 
    :param pointMax: 
    :type pointMax: geometry POINT
    :param pointMin: 
    :type pointMin: geometry POINT
    """
    geometryManager = GeometryLocator.getGeometryManager()
  
    if all((pointMax, pointMin)):
        envelope = geometryManager.createEnvelope(pointMax, pointMin)
    else:
        envelope = geometryManager.createEnvelope()    
  
    return envelope
    

def main():
  point = createPoint(1,1)
