
from org.gvsig.app import ApplicationLocator
from org.gvsig.fmap.dal.feature import FeatureType
from java.util.prefs import Preferences
from org.gvsig.fmap.mapcontext import MapContextLocator
from java.awt import Color

def createFeatureType(schema = None):
  """Returns attributes definition. If Schema is recived then makes a copy and 
  returns editable instance. Otherwise returns empty Schema.
  :param schema: Schema to make a copy
  :type schema: Schema
  """
  if isinstance(schema, FeatureType):
    try:  
      s = schema.getCopy().getEditable()
      return s
    except:
      pass
    
  application = ApplicationLocator.getManager()
  datamanager =  application.getDataManager()
  return datamanager.createFeatureType()

createSchema = createFeatureType

def createLayer(schema, servertype, layertype=None, **parameters):
  """
  Returns new layer
  :param schema: layer data definition
  :type schema: Schema
  :param servertype: 
  :type servertype: string
  :return: new layer
  :rtype: Layer
  :raise: RuntimeException
  """
  if layertype == None:
    layertype = servertype
    servertype = "FilesystemExplorer"

  if layertype == "Shape" :
    if schema.get("GEOMETRY",None) == None:
      raise RuntimeException("Shape need a field named GEOMETRY in the schema")
    
  if parameters["geometryType"] == None:
    raise RuntimeException("Invalid geometry type for new layer")
      
  try:
    application = ApplicationLocator.getManager()
    datamanager =  application.getDataManager()

    mapcontextmanager = application.getMapContextManager()

    server_parameters = datamanager.createServerExplorerParameters(servertype)
    copyToDynObject(parameters, server_parameters)

    server = datamanager.openServerExplorer(servertype, server_parameters)

    store_parameters = server.getAddParameters(layertype)
    copyToDynObject(parameters, store_parameters)
    store_parameters.setDefaultFeatureType(schema)

    server.add(layertype, store_parameters, True)

    store = datamanager.openStore(layertype, store_parameters)

    layer = mapcontextmanager.createLayer(store.getName(), store)

    return layer
  
  except Throwable, ex:
    raise RuntimeException("Can't create layer, "+ str(ex))

def loadShapeFile(shpFile, CRS="CRS:84"):
    """
    Add existing shape file to the view. Returns Layer shape file
    :param shpFile: absolute file path
    :type: shpFile: string
    :param CRS: projection code
    :type CRS: string
    :return: the shape
    :type return: Layer
    """
    layer = loadLayer('Shape', shpFile=shpFile, CRS=CRS)
    currentView().addLayer(layer)
    layer.setActive(True)
    return layer
    
def loadLayer(layerType, **parameters):
    try:
        application = ApplicationLocator.getManager()
        datamanager =  application.getDataManager()
        mapcontextmanager = application.getMapContextManager()
        store_parameters = datamanager.createStoreParameters(layerType)
        copyToDynObject(parameters, store_parameters)
        store = datamanager.openStore(layerType, store_parameters)        
        layer = mapcontextmanager.createLayer(store.getName(), store)
    except Throwable, ex:
        raise RuntimeException("Can't load layer, "+ str(ex))  

    return layer
    
def createShape(definition, filename, geometryType, CRS="CRS:84"):
  """
  Return new shape layer 
  :param definition: layer data definition
  :type definition: Schema
  :param filename: absolute path for shape files. 
  :type filename: string
  :param geometryType: geometry type for shape
  :type geometryType: string
  :return: new shape layer
  :rtype: Layer
  """
  return createLayer(
    definition, 
    "FilesystemExplorer", 
    "Shape", 
    shpFile=filename, 
    CRS=CRS,
    geometryType = geometryType
  )

def createTable(schema, servertype, tableType=None, **parameters):
  """Creates a new Table document"""
  if tableType == None:
    tableType = servertype
    servertype = "FilesystemExplorer"

  try:
    application = ApplicationLocator.getManager()
    datamanager =  application.getDataManager()
    
    server_parameters = datamanager.createServerExplorerParameters(servertype)
    copyToDynObject(parameters, server_parameters)

    server = datamanager.openServerExplorer(servertype, server_parameters)
    
    store_parameters = server.getAddParameters(tableType)
    copyToDynObject(parameters, store_parameters)
    store_parameters.setDefaultFeatureType(schema())
    
    server.add(tableType, store_parameters, True)

    store = datamanager.openStore(tableType, store_parameters)
    
    return store
  
  except Throwable, ex:
    raise RuntimeException("Can't create table, "+ str(ex))
  
def createDBF(definition, DbfFile, CRS="CRS:84"):
  """
  Creates a new dbf document 
  :param definition: layer data definition
  :type definition: Schema
  :param DbfFile: absolute path for shape files. 
  :type DbfFile: string
  :return: new dbf
  :rtype: Table    
  """
  return createTable(
    definition, 
    "FilesystemExplorer", 
    "DBF", 
    DbfFile=DbfFile, 
    CRS=CRS,
  )


#=====================#
# Simbology Functions #
#=====================#  
COLORS = {
    'black': Color.black,
    'blue': Color.blue,
    'cyan': Color.cyan,
    'darkGray': Color.darkGray,
    'gray': Color.gray,
    'green': Color.green,
    'lightGray': Color.lightGray,
    'magenta': Color.magenta,
    'orange': Color.orange,
    'pink': Color.pink,
    'red': Color.red,
    'white': Color.white,
    'yellow': Color.yellow,
}
  
def simplePointSymbol(color=None):
  """
  Returns simple point symbol using parameter color. If no color 
  use a ramdom color
  :param color: String color name or Java awt Color
  :return: gvSIG point symbol
  """
  if isinstance(color, str) and COLORS.has_key(color.lower()):
    color = COLORS.get(color)
    
  if not isinstance(color, Color):
      color = getDefaultColor()
      
  return MapContextLocator.getSymbolManager().createSymbol(
        Geometry.TYPES.POINT, color)

def simpleLineSymbol(color=None):
  """
  Returns simple line symbol using parameter color. If no color use a 
  ramdom color  
  :param color: String color name or Java awt Color
  :return: gvSIG line symbol
  
  """
  if isinstance(color, str) and COLORS.has_key(color.lower()):
    color = COLORS.get(color)

  if not isinstance(color, Color):
      color = getDefaultColor()
      
  return MapContextLocator.getSymbolManager().createSymbol(
        Geometry.TYPES.CURVE, color)

def simplePolygonSymbol(color = None):
  """
  Returns simple polygon symbol using parameter color. If no color 
  use a ramdom color.  
  :param color: String color name or Java awt Color
  :return: gvSIG polygon symbol
  """
  if isinstance(color, str) and COLORS.has_key(color.lower()):
    color = COLORS.get(color)

  if not isinstance(color, Color):
      color = getDefaultColor()
  
  return MapContextLocator.getSymbolManager().createSymbol(
        Geometry.TYPES.SURFACE, color)
  

#=========================================#
# gvSIG Application Preferences Functions #
#=========================================#  

def getDataFolder():
  """
  Returns gvSIG data folder. This folder is defined in application 
  preferences. If is not defined returns None.
  """
  return Preferences.userRoot().node("gvsig.foldering").get('DataFolder', None)
  
def getProjectsFolder():
  """
  Returns gvSIG projects folder. This folder is defined in application 
  preferences. If is not defined returns None.
  """
  return Preferences.userRoot().node("gvsig.foldering").get(
        'ProjectsFolder', None)

def getColorFromRGB(r, g, b, a=None):
  """
  Returns an sRGB color with the specified red, green, blue, and alpha 
  (optional) values in the range (0 - 255).
  """
  if a:
    color = Color(r, g, b, a)
  else:
    color = Color(r, g, b)
  
  return color
  
def getDefaultColor(c = None):
  """Returns gvsig default symbol fill color or ramdom color"""
  if MapContextLocator.getSymbolManager().isDefaultSymbolFillColorAleatory():
    color = Color(random.randint(0-255), 
                random.randint(0-255), 
                random.randint(0-255)
            )
  else:
    sp = MapContextLocator.getSymbolManager().getSymbolPreferences()
    color = sp.getDefaultSymbolFillColor()    

  return color  
  
#================#
# OTHER          #
#================#

def getCRS(crs):
  """Returns Projection from string code (i.e. CRS:84) if exist or None if 
  not.  
  """
  try:
    return CRSFactory.getCRS(crs)
  except:
    return None

def copyToDynObject(values, target):
  definition = target.getDynClass();
  fields = definition.getDynFields();
  for field in fields:
    name = field.getName()
    keys = values.keys()
    for k in keys:
      if k.lower() == name.lower():
        target.setDynValue(name, values[name])
        break
# ====================================
#

