// SPDX-License-Identifier: GPL-3.0-or-later

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright (C) 2013 - 2024, nymea GmbH
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
*
* This file is part of nymea-app.
*
* nymea-app 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 3 of the License, or
* (at your option) any later version.
*
* nymea-app is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with nymea-app. If not, see <https://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

import QtQuick 2.4
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.2
import Nymea 1.0
import "../components"

ItemDelegate {
    id: root

    property ParamType paramType: null
    property StateType stateType: null
    property var value: null
    property int operatorType: ParamDescriptors.ValueOperatorEquals

    readonly property string type: paramType ? paramType.type.toLowerCase() : stateType ? stateType.type.toLowerCase() : ""
    readonly property var minValue: paramType ? paramType.minValue : stateType ? stateType.minValue : undefined
    readonly property var maxValue: paramType ? paramType.maxValue : stateType ? stateType.maxValue : undefined
    readonly property var allowedValues: paramType ? paramType.allowedValues : stateType ? stateType.allowedValues : undefined
    readonly property int unit: paramType ? root.paramType.unit : root.stateType.unit
    contentItem: ColumnLayout {
        Label {
            Layout.fillWidth: true
            text: root.paramType ? root.paramType.displayName : root.stateType.displayName
        }
        RowLayout {
            Layout.fillWidth: true
            spacing: app.margins
            ComboBox {
                FontMetrics {
                    id: fm
                }
                textRole: "text"

                Layout.fillWidth: true
                Layout.minimumWidth: {
                    var minWidth = 0;
                    for (var i = 0; i < model.length; i++) {
                        minWidth = Math.max(minWidth, fm.boundingRect(model[i]).width)
                    }
                    return minWidth + 60;
                }

                property bool isNumeric: {
                    switch (root.type) {
                    case "bool":
                    case "string":
                    case "qstring":
                    case "color":
                        return false;
                    case "uint":
                    case "int":
                    case "double":
                        return true;
                    }
                    console.warn("ParamDescriptorDelegate: Unhandled data type:", root.type);
                    return false;
                }

                model: isNumeric ?
                           numericModel
                         : nonNumericModel

                ListModel {
                    id: numericModel
                    ListElement { text: qsTr("is equal to"); value: ParamDescriptor.ValueOperatorEquals }
                    ListElement { text: qsTr("is not equal to"); value: ParamDescriptor.ValueOperatorNotEquals }
                    ListElement { text: qsTr("is greater than"); value: ParamDescriptor.ValueOperatorGreater }
                    ListElement { text: qsTr("is less than"); value: ParamDescriptor.ValueOperatorLess }
                    ListElement { text: qsTr("is greater than or equal to"); value: ParamDescriptor.ValueOperatorGreaterOrEqual }
                    ListElement { text: qsTr("is less than or equal to"); value: ParamDescriptor.ValueOperatorLessOrEqual }
                }

                ListModel {
                    id: nonNumericModel
                    ListElement { text: qsTr("is"); value: ParamDescriptor.ValueOperatorEquals }
                    ListElement { text: qsTr("is not "); value: ParamDescriptor.ValueOperatorNotEquals }
                }

                onCurrentIndexChanged: {
                    root.operatorType = model.get(currentIndex).value
                    print("set operator to", root.operatorType, currentText, currentIndex, model, model.get(currentIndex))
                }
            }


            Loader {
                id: placeHolder
                Layout.fillWidth: true

                sourceComponent: {
                    print("Datatye is:", root.type, root.minValue, root.maxValue, root.allowedValues)
                    switch (root.type) {
                    case "bool":
                        return boolComponent;
                    case "uint":
                    case "int":
                    case "double":
                        if (root.minValue !== undefined && root.maxValue !== undefined) {
                            return labelComponent;
                        }
                        return spinboxComponent;
                    case "string":
                    case "qstring":
                    case "color":
                        if (root.allowedValues.length > 0) {
                            return comboBoxComponent
                        }
                        return textFieldComponent;
                    }
                    console.warn("ParamDescriptorDelegate: Type delegate not implemented", root.type)
                    return null;
                }
            }

            Label {
                text: Types.toUiUnit(root.unit)
                visible: root.unit !== Types.UnitNone
            }
        }

        Loader {
            Layout.fillWidth: true
            sourceComponent: {
                switch (root.type) {
                case "uint":
                case "int":
                case "double":
                    if (root.minValue !== undefined && root.maxValue !== undefined) {
                        return sliderComponent
                    }


                }
            }
        }

    }

    Component {
        id: labelComponent
        Label {
            text: {
                switch (root.type.toLowerCase()) {
                case "double":
                    return Math.round(Types.toUiValue(root.value, root.unit) * 10) / 10
                }
                return Types.toUiValue(root.value, root.unit)
            }
        }
    }

    Component {
        id: textFieldComponent
        TextField {
            text: ""
            onTextChanged: {
                root.value = text;
            }
            Component.onCompleted: {
                if (root.value == null || root.v^alue == undefined) {
                    root.value = ""
                }
            }
        }
    }

    Component {
        id: sliderComponent
        RowLayout {
            spacing: app.margins
            Label { text: Types.toUiValue(root.minValue, root.unit) }
            Slider {
                from: root.minValue
                to: root.maxValue
                value: root.value
                stepSize: {
                    switch (root.type.toLowerCase()) {
                    case "double":
                        return 0.1
                    }
                    return 1
                }
                Layout.fillWidth: true
                onMoved: {
                    root.value = value;
                }

                Component.onCompleted: {
                    if (root.value == null || root.value == undefined) {
                        root.value = from;
                    }
                }
            }
            Label { text: Types.toUiValue(root.maxValue, root.unit) }
        }

    }

    Component {
        id: spinboxComponent
        NymeaSpinBox {
            from: root.minValue
            to: root.maxValue
            value: root.value != undefined ? root.value : 0
            onValueModified: root.value = value
            floatingPoint: root.type === "double"
            Component.onCompleted: {
                if (root.value == null || root.v^alue == undefined) {
                    root.value = from
                }
            }
        }
    }

    Component {
        id: boolComponent
        ComboBox {
            model: ListModel {
                ListElement { modelData: "true"; value: true }
                ListElement { modelData: "false"; value: false }
            }
            onCurrentIndexChanged: {
                root.value = model.get(currentIndex).value
            }
            Component.onCompleted: {
                if (root.value == null || root.v^alue == undefined) {
                    root.value = model.get(currentIndex).value
                }
            }
        }
    }

    Component {
        id: comboBoxComponent
        ComboBox {
            model: root.allowedValues
            onCurrentIndexChanged: {
                root.value = root.allowedValues[currentIndex]

            }
            Component.onCompleted: {
                if (root.value == null || root.v^alue == undefined) {
                    root.value = root.allowedValues[currentIndex]
                }
            }
        }
    }
}
