"""
/***************************************************************************
 SurfaceWaterStorage
                                 A QGIS plugin
 This plugin calculates the area flooded by water volume, height, elevation 
 or area, and the Area-Elevation-Volume graph
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2024-11-13
        copyright            : (C) 2024 by João Vitor Pimenta
        email                : jvpjoaopimenta@gmail.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__ = 'João Vitor Pimenta'
__date__ = '2024-07-13'
__copyright__ = '(C) 2024 by João Vitor Pimenta'

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

__revision__ = '$Format:%H$'

import processing
from scipy.integrate import cumulative_trapezoid
from numpy import loadtxt, append, column_stack
from plotly.graph_objects import Scatter
from plotly.subplots import make_subplots
from qgis.core import QgsProcessingException
from ..exceptions.processingExceptions import verifyNumberOfPointsInCurve

def executePlugin (dem,area,step):
    '''
    uses input parameters to execute plugin functions
    '''
    hypsometricCurve = generateHypsometricCurve(dem,area,step)
    verifyNumberOfPointsInCurve(hypsometricCurve)
    areaHeightVolumeCSV = calculateAreaHeightVolume(hypsometricCurve)
    graph = createGraph(areaHeightVolumeCSV)

    return areaHeightVolumeCSV, graph
def generateHypsometricCurve (dem,area,step):
    '''
    generates hypsometric curve data
    '''
    params = {
            'INPUT_DEM':dem,
            'BOUNDARY_LAYER':area,
            'STEP':step,
            'USE_PERCENTAGE':False,
            'OUTPUT_DIRECTORY':'TEMPORARY_OUTPUT'
    }

    hypsometricCurve = processing.run(
                                        "qgis:hypsometriccurves",
                                        params
                                        )['OUTPUT_DIRECTORY']
    maskName = area.sourceName()
    features = area.getFeatures()
    feature = next(features, None)
    featureID = feature.id()
    path = hypsometricCurve+'/histogram_'+maskName+'_'+str(featureID)+'.csv'

    return path
def calculateAreaHeightVolume (areaHeightCurve):
    '''
    integrates the hypsometric curve, generating elevation-area-volume data
    '''
    data = loadtxt(areaHeightCurve, delimiter=',',skiprows=1)

    verifyNumberOfPointsInCurve(data)

    xd = data[:, 0].tolist()
    yd = data[:, 1].tolist()

    integration = cumulative_trapezoid(xd,yd)
    integrationComplet = append(integration,0)
    dataWithIntegration = column_stack((data,integrationComplet))
    dataWoLastRow = dataWithIntegration[:-1]

    return dataWoLastRow
def createGraph(npAHVData):
    '''
    create a graph with area-height-volume data,
    generating the elevation-area and elevation-volume curves
    '''
    areas = npAHVData[:,0]
    elevations = npAHVData[:,1]
    volumes = npAHVData[:,2]

    fig = make_subplots(specs=[[{"secondary_y": True}]])

    fig.add_trace(Scatter(
                            x=volumes,
                            y=elevations,
                            mode='lines',
                            name='Volume - Elevation'
                            ),
                            secondary_y=False
                            )
    fig.add_trace(Scatter(x=areas,
                            y=elevations,
                            mode='lines',
                            name='Area - Elevation'
                            ),
                            secondary_y=True
                            )

    fig.data[1].update(xaxis='x2')
    fig.update_layout(
        title='Area x Volume x Elevation',
        xaxis=dict(title='Volume (m³)'),
        yaxis=dict(title='Elevation (m)'),
        xaxis2=dict(title='Area (m²)',
                    overlaying='x',
                    side='top',
                    autorange='reversed'),
        yaxis2=dict(
                    title='Elevation (m)',
                    overlaying='y',
                    side='right',
                    position=1
                    )
                        )

    return fig
