/**
 *  LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
 *  Copyright (C) 2022  Ad5001
 * 
 *  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 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
 */

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQml.Models 2.12

/*!
    \qmltype ListSetting
    \inqmlmodule eu.ad5001.LogarithmPlotter.Setting
    \brief Setting to create and edit lists and dictionaries.
            
    \sa EditorDialog, Settings, Icon
*/
Column {
    id: control
    
    /*!
        \qmlsignal ListSetting::changed()
        
        Emitted when an entry of the setting has been changed.
        The corresponding handler is \c onChanged.
    */
    signal changed()
    
    /*!
       \qmlproperty string ListSetting::label
       Label of the setting.
    */
    property string label: ''
    /*!
       \qmlproperty string ListSetting::icon
       Icon path of the setting.
    */
    property string icon: ''
    /*!
       \qmlproperty bool ListSetting::dictionaryMode
       true to set the export mode to dictionary, false for list.
    */
    property bool dictionaryMode: false
    /*!
       \qmlproperty string ListSetting::keyType
       Type for keys for dictionary, can be either "string" or "number".
    */
    property string keyType: "string"
    /*!
       \qmlproperty string ListSetting::keyType
       Type for values of the dictionary or list, can be either "string" or "number".
    */
    property string valueType: "string"
    /*!
       \qmlproperty string ListSetting::preKeyLabel
       Text to be put before the key for each entry.
    */
    property string preKeyLabel: ""
    /*!
       \qmlproperty string ListSetting::postKeyLabel
       Text to be put after the key for each entry. Only for dictionaries.
    */
    property string postKeyLabel: ": "
    /*!
       \qmlproperty var ListSetting::keyRegexp
       Regular expression used in the validator for keys. Only for dictionaries.
    */
    property var keyRegexp: /^.+$/
    /*!
       \qmlproperty var ListSetting::valueRegexp
       Regular expression used in the validator for values.
    */
    property var valueRegexp: /^.+$/
    /*!
       \qmlproperty bool ListSetting::forbidAdding
       If true, prevents the user from adding or removing new entries.
    */
    property bool forbidAdding: false
    
    /*!
       \qmlproperty bool ListSetting::model
       Model of the list/dictionnary, in the form of [{key: < key >, val: < value > }].
       
       Use the \a importModel method to set the model.
    */
    property alias model: repeater.model
    
    Row {
        height: 30
        width: parent.width;
        Icon {
            id: iconLabel
            anchors.top: parent.top
            anchors.topMargin: icon == "" ? 0 : 3
            source: control.visible ? "../icons/" + control.icon : ""
            width: height
            height: icon == "" || !visible ? 0 : 24
            color: sysPalette.windowText
        }
        Label {
            id: labelItem
            height: 30
            verticalAlignment: TextInput.AlignVCenter
            text: qsTranslate("control", "%1: ").arg(control.label)
        }
    }
    
    Repeater {
        id: repeater
        width: control.width
        model: ListModel {}
        
        Row {
            id: defRow
            height: addEntryBtn.height
            width: parent.width
            
            Text {
                id: preKeyText
                height: parent.height
                verticalAlignment: TextInput.AlignVCenter
                color: sysPalette.windowText
                text: control.preKeyLabel
            }
            
            TextField {
                id: keyInput
                visible: control.dictionaryMode
                height: parent.height
                width: visible ? 50 : 0
                validator: RegExpValidator { 
                    regExp: control.keyRegexp
                }
                verticalAlignment: TextInput.AlignVCenter
                horizontalAlignment: TextInput.AlignHCenter
                color: sysPalette.windowText
                text: visible ? control.model.get(index).key : false
                selectByMouse: true
                onEditingFinished: {
                    var value = text
                    if(control.keyType == 'int') {
                        value = parseInt(value)
                        if(value.toString()=="NaN")
                            value = ""
                    }
                    if(control.keyType == 'double') {
                        value = parseFloat(value)
                        if(value.toString()=="NaN")
                            value = ""
                    }
                    if(value !== "" && valueInput.acceptableInput) {
                        control.model.setProperty(index, 'key', value)
                        control.changed()
                    }
                }
            }
            
            Text {
                id: postKeyText
                visible: control.dictionaryMode
                height: parent.height
                verticalAlignment: TextInput.AlignVCenter
                color: sysPalette.windowText
                text: control.postKeyLabel
            }
            
            TextField {
                id: valueInput
                height: parent.height
                width: parent.width - x - deleteButton.width - 5
                validator: RegExpValidator { 
                    regExp: control.valueRegexp
                }
                verticalAlignment: TextInput.AlignVCenter
                horizontalAlignment: TextInput.AlignHCenter
                color: sysPalette.windowText
                text: visible ? control.model.get(index).val : false
                selectByMouse: true
                onEditingFinished: {
                    var value = text
                    if(control.valueType == 'int') {
                        value = parseInt(value)
                        if(value.toString()=="NaN")
                            value = ""
                    }
                    if(control.valueType == 'double') {
                        value = parseFloat(value)
                        if(value.toString()=="NaN")
                            value = ""
                    }
                    if(value !== "" && keyInput.acceptableInput) {
                        control.model.setProperty(index, 'val', value)
                        control.changed()
                    }
                }
            }
            
            Item {
                width: 5
                height: parent.height
            }
            
            Button {
                id: deleteButton
                width: visible ? parent.height : 0
                height: width
                icon.source: './icons/common/delete.svg'
                icon.name: 'delete'
                visible: !control.forbidAdding
                
                onClicked: {
                    control.model.remove(index)
                }
            }
        }
    }
    
    Button {
        id: addEntryBtn
        visible: !control.forbidAdding
        text: qsTr('+ Add Entry')
        width: control.width
        
        onClicked: {
            control.model.append({
                key: control.keyType == 'string' ? '' : model.count,
                val: control.valueType == 'string' ? '' : 0
            })
        }
    }
    
    /*!
        \qmlmethod void ListSetting::importModel(var importer)
        Imports either a list or a dictionnary in the model.
    */
    function importModel(importer) {
        model.clear()
        for(var key in importer) 
            model.append({
                key: control.keyType == 'string' ? key.toString() : parseFloat(key),
                val: control.valueType == 'string' ? importer[key].toString() : parseFloat(importer[key])
            })
    }
    
    
    /*!
        \qmlmethod void ListSetting::exportModel()
        Exports the model either a list or a dictionnary in the model depending on \a dictionaryMode.
    */
    function exportModel() {
        if(dictionaryMode) {
            var ret = {}
            for(var i = 0; i < model.count; i++)
                ret[model.get(i).key] = model.get(i).val
            return ret
        } else {
            var ret = []
            for(var i = 0; i < model.count; i++)
                ret.push(model.get(i).val)
            return ret
        }
    }
}
