"""
***************************************************************************
    ExecuteSQLWidget.py
    ---------------------
    Date                 : November 2017
    Copyright            : (C) 2017 by Paul Blottiere
    Email                : blottiere dot paul 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__ = 'Paul Blottiere'
__date__ = 'November 2018'
__copyright__ = '(C) 2018, Paul Blottiere'

import os

from qgis.PyQt import uic

from qgis.core import (
    Qgis,
    QgsExpressionContextScope,
    QgsProcessingParameterString,
    QgsProcessingParameterNumber,
    QgsExpression,
    QgsProcessingModelChildParameterSource
)

from qgis.gui import QgsFieldExpressionWidget

from processing.gui.wrappers import (WidgetWrapper,
                                     dialogTypes,
                                     DIALOG_MODELER)

pluginPath = os.path.dirname(__file__)
WIDGET, BASE = uic.loadUiType(os.path.join(pluginPath, 'ExecuteSQLWidgetBase.ui'))


class ExecuteSQLWidget(BASE, WIDGET):

    def __init__(self, dialog):
        super().__init__(None)
        self.setupUi(self)
        self.dialog = dialog
        self.dialogType = dialogTypes[dialog.__class__.__name__]

        self.mExpressionWidget = QgsFieldExpressionWidget()

        # add model parameters in context scope if called from modeler
        if self.dialogType == DIALOG_MODELER:
            strings = dialog.getAvailableValuesOfType(
                [QgsProcessingParameterString, QgsProcessingParameterNumber], [])
            model_params = [dialog.resolveValueDescription(s) for s in strings]

            scope = QgsExpressionContextScope()
            for param in model_params:
                var = QgsExpressionContextScope.StaticVariable(param)
                scope.addVariable(var)

            self.mExpressionWidget.appendScope(scope)

        self.mHLayout.insertWidget(0, self.mExpressionWidget)

        self.mInsert.clicked.connect(self.insert)

    def insert(self):
        if self.mExpressionWidget.currentText():
            exp = f'[%{self.mExpressionWidget.currentText()}%]'
            self.mText.insertPlainText(exp)

    def setValue(self, value):
        text = value

        if self.dialogType == DIALOG_MODELER:
            if isinstance(value, list):
                for v in value:
                    if isinstance(v, QgsProcessingModelChildParameterSource) \
                            and v.source() == Qgis.ProcessingModelChildParameterSource.ExpressionText:
                        text = v.expressionText()

                        # replace parameter's name by expression (diverging after model save)
                        names = QgsExpression.referencedVariables(text)

                        strings = self.dialog.getAvailableValuesOfType(
                            [QgsProcessingParameterString, QgsProcessingParameterNumber], [])
                        model_params = [(self.dialog.resolveValueDescription(s), s) for s in strings]

                        for k, v in model_params:
                            if v.parameterName() in names:
                                text = text.replace(f'[% @{v.parameterName()} %]', f'[% @{k} %]')

        self.mText.setPlainText(text)

    def value(self):
        value = self.mText.toPlainText()

        if self.dialogType == DIALOG_MODELER:
            expression_values = self._expressionValues(value)
            if len(expression_values) > 1:
                value = expression_values

        return value

    def _expressionValues(self, text):
        strings = self.dialog.getAvailableValuesOfType(
            [QgsProcessingParameterString, QgsProcessingParameterNumber], [])
        model_params = [(self.dialog.resolveValueDescription(s), s) for s in strings]

        variables = QgsExpression.referencedVariables(text)

        # replace description by parameter's name (diverging after model save)
        descriptions = QgsExpression.referencedVariables(text)

        for k, v in model_params:
            if k in descriptions:
                text = text.replace(f'[% @{k} %]', f'[% @{v.parameterName()} %]')

        src = QgsProcessingModelChildParameterSource.fromExpressionText(text)

        # add parameters currently used by the expression
        expression_values = [src]

        for k, v in model_params:
            if k in variables:
                expression_values.append(v)

        return expression_values


class ExecuteSQLWidgetWrapper(WidgetWrapper):

    def createWidget(self):
        return ExecuteSQLWidget(self.dialog)

    def setValue(self, value):
        self.widget.setValue(value)

    def value(self):
        return self.widget.value()
