# script to run in the Python console

import os

import json
import psycopg2

from qgis.utils import iface

DEFAULT_PLOT_SIZE = 150

# Delete the current available layers
QgsProject.instance().removeAllMapLayers()
QgsProject.instance().layerTreeRoot().clear()

# Read the measure metadata in the database to tune the accurate data
conn = psycopg2.connect("service=qgeologistest")
cur = conn.cursor()
cur.execute("select * from measure.measure_metadata")


def add_layer(source, name, provider, group=None):
    """Add a layer to the QGIS project, with respect to some connexion parameters.

    Parameters
    ----------
    source : str
        Layer source.
    name : str
        Layer display name in the layer list
    provider : str
        Layer provider.
    group : str
        If None the layer is set a root layer, otherwise the layer is stored into the
    given group

    Returns
    -------
    QgsVectorLayer
        Layer that will be added to the QGIS project.
    """
    layer = QgsVectorLayer(source, name, provider)
    QgsProject.instance().addMapLayer(layer, addToLegend=group is None)
    if group is not None:
        group.addLayer(layer)
    return layer


# Define the main layer, that contains stations
main_layer = add_layer(
    """service='qgeologistest' sslmode=disable key='id' srid=4326 type=Point checkPrimaryKeyUnicity='0' table="qgis"."station" (point) sql=""",
    "Stations",
    "postgres",
)

# Define a group for all measure layers
root_group = iface.layerTreeView().layerTreeModel().rootGroup()
group = root_group.addGroup("Mesures")

# Add some noticeable layers, with particularities to handle
strat_layer = add_layer(
    """service='qgeologistest' sslmode=disable key='depth_from,depth_to,station_id' checkPrimaryKeyUnicity='0' table="qgis"."measure_stratigraphic_logvalue" sql=""",
    "Stratigraphie",
    "postgres",
    group,
)
chem_layer = add_layer(
    """service='qgeologistest' sslmode=disable key='id' table="qgis"."measure_chemical_analysis_result" checkPrimaryKeyUnicity='0' sql=""",
    "Analyse chimique",
    "postgres",
    group,
)
chimney_layer = add_layer(
    """service='qgeologistest' sslmode=disable key='id' table="qgis"."measure_chimney_release" checkPrimaryKeyUnicity='0' sql=""",
    "Rejet",
    "postgres",
    group,
)
fracturation_layer = add_layer(
    """service='qgeologistest' sslmode=disable key='station_id,depth_from,depth_to' table="qgis"."measure_fracturing_rate" checkPrimaryKeyUnicity='0' sql=""",
    "Fracturation",
    "postgres",
    group,
)

# Initialize the log measures (with respect to the depth axis)
log_measures = [
    {
        "source": fracturation_layer.id(),
        "name": fracturation_layer.name(),
        "feature_ref_column": "station_id",
        "type": "cumulative",
        "min_event_column": "depth_from",
        "max_event_column": "depth_to",
        "value_column": "value",
        "uom": "-",
        "displayed_uom": "-",
        "scale_type": "linear",
        "plot_size":DEFAULT_PLOT_SIZE,
        "uncertainty_column": None,
        "feature_filter_type": "None",
        "display": "1",
        "displayed_cat":[],
        "stacked": {}
    }
]

# Initialize the timeseries (with respect to the time axis)
timeseries = [
    {
        "source": chem_layer.id(),
        "name": chem_layer.name(),
        "uom_column": "measure_unit",
        "feature_ref_column": "station_id",
        "feature_filter_type": "unique_data_from_values",
        "feature_filter_column": "chemical_element",
        "displayed_cat":['Al'],
        "type": "instantaneous",
        "event_column": "measure_epoch",
        "value_column": "measure_value",
        "uncertainty_column": "measure_uncertainty",
        "scale_type": "linear",
        "plot_size":DEFAULT_PLOT_SIZE,
        "min": None,
        "max": None,
        "display": "0",
        "stacked": {}
    },
    {
        "source": chimney_layer.id(),
        "name": chimney_layer.name(),
        "uom": "m³",
        "displayed_uom": "m³",
        "feature_ref_column": "station_id",
        "feature_filter_type": "unique_data_from_values",
        "feature_filter_column": "chemical_element",
        "displayed_cat":[],
        "type": "cumulative",
        "min_event_column": "start_epoch",
        "max_event_column": "end_epoch",
        "value_column": "measure_value",
        "uncertainty_column": "measure_uncertainty",
        "scale_type": "linear",
        "plot_size":DEFAULT_PLOT_SIZE,
        "min": None,
        "max": None,
        "display": "0",
        "stacked": {}
    },
]

# Initialize the image layers
imagery_data = []

# For the remaining layers, just follow the measure metadata from the database
for table_name, name, uom, x_type, storage_type in cur.fetchall():
    schema, table = table_name.split(".")
    if table in ("fracturing_rate", "chimney_release"):
        continue
    layer = add_layer(
        """service='qgeologistest' sslmode=disable key='id' checkPrimaryKeyUnicity='0' table="qgis"."{}_{}" sql=""".format(
            schema, table
        ),
        name,
        "postgres",
        group,
    )
    if x_type == "TimeAxis":
        # time series
        if storage_type == "Continuous":
            timeseries.append(
                {
                    "source": layer.id(),
                    "name": name,
                    "uom": uom,
                    "displayed_uom": uom,
                    "feature_ref_column": "station_id",
                    "type": storage_type.lower(),
                    "start_measure_column": "start_epoch",
                    "interval_column": "interval_s",
                    "values_column": "measures",
                    "uncertainty_column": None,
                    "scale_type": "linear",
                    "plot_size":DEFAULT_PLOT_SIZE,
                    "min": None,
                    "max": None,
                    "display": "1",
                    "stacked": {}
                }
            )
        elif storage_type == "Instantaneous":
            timeseries.append(
                {
                    "source": layer.id(),
                    "name": name,
                    "uom": uom,
                    "displayed_uom": uom,
                    "feature_ref_column": "station_id",
                    "type": storage_type.lower(),
                    "event_column": "measure_epoch",
                    "value_column": "measure_value",
                    "uncertainty_column": None,
                    "scale_type": "linear",
                    "plot_size":DEFAULT_PLOT_SIZE,
                    "min": None,
                    "max": None,
                    "feature_filter_type": "None",
                    "displayed_cat":[],
                    "nodata": "remove",
                    "display": "1",
                    "stacked": {}
                }
            )
        elif storage_type == "Cumulative":
            timeseries.append(
                {
                    "source": layer.id(),
                    "name": name,
                    "uom": uom,
                    "displayed_uom": uom,
                    "feature_ref_column": "station_id",
                    "type": storage_type.lower(),
                    "min_event_column": "start_epoch",
                    "max_event_column": "end_epoch",
                    "value_column": "measure_value",
                    "uncertainty_column": None,
                    "scale_type": "linear",
                    "plot_size":DEFAULT_PLOT_SIZE,
                    "min": None,
                    "max": None,
                    "feature_filter_type": "None",
                    "displayed_cat":[],
                    "display": "1",
                    "stacked": {}
                }
            )
    elif x_type == "DepthAxis":
        if storage_type == "Image":
            imagery_data.append(
                {
                    "type": "image",
                    "name": name,
                    "source": layer.id(),
                    "conn": "service=qgeologistest",
                    "schema": "qgis",
                    "table": "measure_{}".format(table),
                    "feature_ref_column": "station_id",
                    "plot_size":DEFAULT_PLOT_SIZE,
                    "displayed_cat":[],
                    "display": "1",
                    "stacked": {}
                }
            )
        elif storage_type == "Continuous":
            log_measures.append(
                {
                    "source": layer.id(),
                    "name": name,
                    "uom": uom,
                    "displayed_uom": uom,
                    "feature_ref_column": "station_id",
                    "type": storage_type.lower(),
                    "start_measure_column": "start_measure_altitude",
                    "interval_column": "altitude_interval",
                    "values_column": "measures",
                    "uncertainty_column": None,
                    "scale_type": "linear",
                    "plot_size":DEFAULT_PLOT_SIZE,
                    "min": None,
                    "max": None,
                    "feature_filter_type": "None",
                    "displayed_cat":[],
                    "display": "1",
                    "stacked": {}
                }
            )
        elif storage_type == "Cumulative":
            log_measures.append(
                {
                    "source": layer.id(),
                    "name": name,
                    "uom": uom,
                    "displayed_uom": uom,
                    "feature_ref_column": "station_id",
                    "type": storage_type.lower(),
                    "min_event_column": "depth_from",
                    "max_event_column": "depth_to",
                    "value_column": "value",
                    "uncertainty_column": None,
                    "scale_type": "linear",
                    "plot_size":DEFAULT_PLOT_SIZE,
                    "min": None,
                    "max": None,
                    "feature_filter_type": "None",
                    "displayed_cat":[],
                    "display": "1",
                    "stacked": {}
                }
            )

# Finalize the QGeoloGIS layer configuration
config = {
    main_layer.id(): {
        "layer_name": "Stations",
        "id_column": "id",
        "name_column": "name",
        "ground_elevation": "ground_altitude",
        "stratigraphy_config": [
            {
                "source": strat_layer.id(),
                "name": strat_layer.name(),
                "feature_ref_column": "station_id",
                "depth_from_column": "depth_from",
                "depth_to_column": "depth_to",
                "formation_code_column": "formation_code",
                "rock_code_column": "rock_code",
                "formation_description_column": "formation_description",
                "rock_description_column": "rock_description",
                "type": "stratigraphic",
                "plot_size":DEFAULT_PLOT_SIZE,
                "display": "1",
                "displayed_cat":[],
                "stacked": {}
            }
        ],
        "log_measures": log_measures,
        "timeseries": timeseries,
        "imagery_data": imagery_data,
    }
}

# Write the configuration into a json file and update the QGIS project
json_dumps = json.dumps(config)
QgsProject.instance().writeEntry("QGeoloGIS", "config", json_dumps)

if QgsProject.instance().homePath() == "":
    projectPath = os.path.join(
        QgsApplication.qgisSettingsDirPath(),
        "python",
        "plugins",
        "QGeoloGIS",
        "sample",
        "project.qgs",
    )
    QgsProject.instance().write(projectPath)
else:
    QgsProject.instance().write()

# Read project will trigger config load
path = QgsProject.instance().fileName()
QgsProject.instance().read(path)
