# -*- coding: utf-8 -*-

"""
***************************************************************************
    ConvexHull.py
    ---------------------
    Date                 : August 2012
    Copyright            : (C) 2012 by Victor Olaya
    Email                : volayaf at gmail dot com
***************************************************************************
*                                                                         *
*   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.                                   *
*                                                                         *
***************************************************************************
"""

__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'

# This will get replaced with a git SHA1 when you do a git archive

__revision__ = '$Format:%H$'

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import \
        GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterTableField
from processing.core.parameters import ParameterSelection
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector


class ConvexHull(GeoAlgorithm):

    INPUT = 'INPUT'
    OUTPUT = 'OUTPUT'
    FIELD = 'FIELD'
    METHOD = 'METHOD'
    METHODS = ['Create single minimum convex hull',
               'Create convex hulls based on field']

    def defineCharacteristics(self):
        self.name = 'Convex hull'
        self.group = 'Vector geometry tools'
        self.addParameter(ParameterVector(ConvexHull.INPUT, 'Input layer',
                          [ParameterVector.VECTOR_TYPE_ANY]))
        self.addParameter(ParameterTableField(ConvexHull.FIELD,
                          'Field (optional, only used if creating convex hulls by classes)',
                          ConvexHull.INPUT, optional=True))
        self.addParameter(ParameterSelection(ConvexHull.METHOD, 'Method',
                          ConvexHull.METHODS))
        self.addOutput(OutputVector(ConvexHull.OUTPUT, 'Convex hull'))

    def processAlgorithm(self, progress):
        useField = self.getParameterValue(ConvexHull.METHOD) == 1
        fieldName = self.getParameterValue(ConvexHull.FIELD)
        layer = dataobjects.getObjectFromUri(
                self.getParameterValue(ConvexHull.INPUT))

        f = QgsField('value')
        f.setType(QVariant.String)
        f.setLength(255)
        if useField:
            index = layer.fieldNameIndex(fieldName)
            fType = layer.pendingFields()[index].type()
            if fType == QVariant.Int:
                f.setType(QVariant.Int)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = [QgsField('id', QVariant.Int, '', 20), f, QgsField('area',
                  QVariant.Double, '', 20, 6), QgsField('perim',
                  QVariant.Double, '', 20, 6)]

        writer = self.getOutputFromName(
                ConvexHull.OUTPUT).getVectorWriter(fields,
                                                   QGis.WKBPolygon,
                                                   layer.dataProvider().crs())

        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        current = 0

        fid = 0
        val = ''
        if useField:
            unique = layer.uniqueValues(index)
            total = 100.0 / float(layer.featureCount() * len(unique))

            for i in unique:
                hull = []
                first = True
                features = vector.features(layer)
                for f in features:
                    idVar = f[fieldName]
                    if unicode(idVar).strip() == unicode(i).strip:
                        if first:
                            val = idVar
                            first = False
                        inGeom = QgsGeometry(f.geometry())
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    progress.setPercentage(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        (area, perim) = vector.simpleMeasure(outGeom)
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        writer.addFeature(outFeat)
                    except:
                        raise GeoAlgorithmExecutionException(
                                'Exception while computing convex hull')
                fid += 1
        else:
            hull = []
            total = 100.0 / float(layer.featureCount())
            features = vector.features(layer)
            for f in features:
                inGeom = QgsGeometry(f.geometry())
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                current += 1
                progress.setPercentage(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                (area, perim) = vector.simpleMeasure(outGeom)
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, 'all', area, perim])
                writer.addFeature(outFeat)
            except:
                raise GeoAlgorithmExecutionException(
                        'Exception while computing convex hull')

        del writer
