# encoding: utf-8

from gvsig import *
from org.gvsig.tools.swing.api.windowmanager import WindowManager
import StringIO
from gvsig.commonsdialog import *
from javax.swing.event import HyperlinkListener
from org.gvsig.fmap.geom import GeometryLocator
from org.gvsig.fmap.geom import Geometry
from org.gvsig.fmap.geom.primitive import NullGeometry
from org.gvsig.tools import ToolsLocator

class Cmdline(object):
  def __init__(self, line):
    self.parse(line)
    
  def parse(self,line):
    cmds = line.split(";")
    self.cmds = list()
    for cmd in cmds:
      cmd = cmd.strip()
      args = None
      n = cmd.find(":")
      if n> 0 :
        args = cmd[n+1:].strip()
        cmd = cmd[:n].strip()
      self.cmds.append((cmd,args))

  def execute(self):
    for cmd,args in self.cmds:
      method = getattr(self,cmd,None)
      try:
        if method!=None:
          method(args)
        else:
          self.call(cmd,args)
      except Exception, ex:
        print "Oopss algo fallo ejecutando ", cmd, args
        print str(ex)

def centerViewinPoint(view,center):
    env = view.getMap().getViewPort().getEnvelope();
    movX = center.getX()-env.getCenter(0);
    movY = center.getY()-env.getCenter(1);
    minx = env.getMinimum(0) + movX;
    miny = env.getMinimum(1) + movY;
    maxX = env.getMaximum(0) + movX;
    maxY = env.getMaximum(1) + movY;
    env = GeometryLocator.getGeometryManager().createEnvelope(
          minx, miny,
          maxX, maxY,
          Geometry.SUBTYPES.GEOM2D);
    view.getMap().getViewPort().setEnvelope(env);
    view.getMap().invalidate()


class MyHyperlinkListener(HyperlinkListener, Cmdline):
  def __init__(self,vista, capa, tabla_de_referencias):
    self.vista = vista
    self.capa = capa
    self.tabla_de_referencias = tabla_de_referencias
    
  def hyperlinkUpdate(self, h):
    if str(h.getEventType()) == "ACTIVATED":
      # Solo procesamos los eventos "ACTIVATED" que son los clicks sobre los enlaces
      # Recogemos la geometria que metimos en el enalce en WKT
      cmdline = h.getDescription()
      #print cmdline
      self.parse(cmdline)
      self.execute()

  def select(self,arg):
    ref = self.tabla_de_referencias.get(arg,None)
    self.capa.getSelection().select(ref)

  def clearSelection(self,arg):
    self.capa.getSelection().deselectAll()

  def center(self,arg):
    # Reconstruimos el punto a partir del WKT en arg
    manager = GeometryLocator.getGeometryManager()
    point = manager.createFrom(arg)
    # Y una vez lo tenemos centramos la vista en ese punto.
    centerViewinPoint(self.vista,point)

  def fixgeometry(self,arg):
    ref = self.tabla_de_referencias.get(arg,None)
    feature = ref.getFeature().getEditable()
    geom = feature.getDefaultGeometry()
    if geom.isValid():
      return
    fixedgeom = geom.makeValid()
    if fixedgeom != None:
      if isinstance(fixedgeom,NullGeometry) :
        fixedgeom = None
      feature.setDefaultGeometry(fixedgeom)
      store = self.capa().getDataStore()
      if not store.isEditing() :
        store.edit()
      store.update(feature)
    
  
def main(*args):
  validate(None)

def validate(taskStatus):
  layer = currentLayer()
  if layer == None:
    msgbox(u"Deberá seleccionar la capa que desea validar")
    return
  if taskStatus == None:
    taskStatusManager = ToolsLocator.getTaskStatusManager()
    taskStatus = taskStatusManager.createDefaultSimpleTaskStatus("validate")
    taskStatus.setAutoremove(True)
    
  output1 = StringIO.StringIO()  
  output2 = StringIO.StringIO()  
  output1.write("<ul>\n")
  output2.write("<ul>\n")
  contador=0
  tabla_de_referencias = dict()
  contador_problemas = 0
  contador_nulos = 0
  try:
    # A�adimos la barra de progreso a la barra de estado de gvSIG
    taskStatus.add()
    # Le indicamos cuantas iteraciones vamos a realizar
    taskStatus.setRangeOfValues(0,layer.features().getCount());
    for feature in layer.features():
      # En cada iteracion informamos a la barra de progreso de por donde vamos
      taskStatus.setCurValue(contador)
      geom = feature.geometry()
      if geom == None:
        contador_nulos += 1
        tabla_de_referencias[str(contador)]= feature().getReference()
        output2.write("<li>")
        output2.write('<a href="select: %s">%5.5d</a> %s<br>%s' % (
            contador, 
            contador, 
            feature.toString(),
            "Null geometry"
          )
        )          
        output2.write("</li>")
      else:
        vs = geom.getValidationStatus();
        if not vs.isValid() :
          tabla_de_referencias[str(contador)]= feature().getReference()
          contador_problemas += 1
          if vs.getStatusCode() == 1 : # Corrupta
            try:
              print contador, geom.getNumVertices(), geom.__class__
            except Exception,ex:
              print contador
              
          geom2 = geom.makeValid()
          if geom2 != None:
            canfix = '(<a href="fixgeometry: %s">Fix</a>)' % contador
          else:
            canfix = ""
          if vs.getProblemLocation()!=None:
            wktgeom = vs.getProblemLocation().convertToWKT()
          else:
            try:
              # Atrapamos los errores no vaya a ser que la geometria este tan da�ada que
              # nos falle el calculo de su centroide.
              wktgeom = feature.geometry().centroid().convertToWKT()
            except:
              wktgeom = None
          output1.write("<li>")
          if wktgeom == None:
            output1.write('<a href="select: %s">%5.5d</a> %s<br>%s %s' % (
                contador, 
                contador, 
                feature.toString(),
                vs.getMessage(),
                canfix
              )
            )
          else:
            output1.write('<a href="clearSelection; select: %s; center: %s">%5.5d</a> %s<br>%s %s' % (
                contador, 
                wktgeom,
                contador, 
                feature.toString(),
                vs.getMessage(),
                canfix
              )
            )
          output1.write("</li>")
      contador+=1
  finally:  
    # Al terminar
    # Le indicamos a la barra de progreso que ya hemos terminado
    taskStatus.terminate()
    # Y la eliminamos de la barra de estado de gvSIG.
    taskStatus.remove()
    
  output1.write("</ul>\n")
  output2.write("</ul>\n")
  
  if contador_problemas>0 or contador_nulos>0 :
    texto = "<p>Se ha detectado:<br><ul><li>%s geometrias con problemas</li><li>%s registros sin geometria.</li></ul></p>" % (
      contador_problemas,
      contador_nulos
    )
    if contador_problemas > 0:
      texto += "Geometrias con problemas:<br>"
      texto += output1.getvalue()
    if contador_nulos > 0:
      texto += "Registros sin geometrias:<br>"
      texto += output2.getvalue()
    application = ApplicationLocator.getManager()
    application.showTextDialog(
      WindowManager.MODE.TOOL, # TOOL o WINDOW segun nos interese.
      "Problems in layer "+layer.getName(),
      texto,
      MyHyperlinkListener(currentView(), layer, tabla_de_referencias)
    )
  else:
    msgbox("Layer "+layer.getName()+" is valid.")


