// SPDX-FileCopyrightText: 2022 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL

import QtQuick 2.15
import QtQuick.Controls 2.15 as QQC2
import QtQuick.Layouts 1.15

import org.kde.kirigami 2.15 as Kirigami
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm
import org.kde.kirigamiaddons.delegates 1.0 as Delegates
import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents
import org.kde.kitemmodels 1.0

import org.kde.neochat 1.0

Kirigami.ScrollablePage {
    id: root

    property NeoChatRoom room

    title: i18nc('@title:window', 'Permissions')
    topPadding: 0
    leftPadding: 0
    rightPadding: 0

    UserListModel {
        id: userListModel
        room: root.room
    }

    ListModel {
        id: powerLevelModel
    }

    ColumnLayout {
        spacing: 0
        MobileForm.FormHeader {
            Layout.fillWidth: true
            title: i18n("Privileged Users")
        }
        MobileForm.FormCard {
            Layout.fillWidth: true
            contentItem: ColumnLayout {
                spacing: 0
                Repeater {
                    model: KSortFilterProxyModel {
                        sourceModel: userListModel
                        sortRole: "powerLevel"
                        sortOrder: Qt.DescendingOrder
                        filterRowCallback: function(source_row, source_parent) {
                            let powerLevelRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), UserListModel.PowerLevelRole)
                            return powerLevelRole > 0;
                        }
                    }
                    delegate: MobileForm.FormTextDelegate {
                        text: name
                        description: userId
                        contentItem.children: RowLayout {
                            spacing: Kirigami.Units.largeSpacing
                            QQC2.Label {
                                visible: !room.canSendState("m.room.power_levels")
                                text: powerLevelString
                                color: Kirigami.Theme.disabledTextColor
                            }
                            QQC2.ComboBox {
                                focusPolicy: Qt.NoFocus // provided by parent
                                model: powerLevelModel
                                textRole: "text"
                                valueRole: "powerLevel"
                                visible: room.canSendState("m.room.power_levels")
                                Component.onCompleted: {
                                    /**
                                     * This is very silly but the only way to populate the model with
                                     * translated strings. Done here because the model needs to be filled
                                     * before the first delegate sets it's current index.
                                     */
                                    if (powerLevelModel.count == 0) {
                                        powerLevelModel.append({"text":  i18n("Member (0)"), "powerLevel": 0});
                                        powerLevelModel.append({"text":  i18n("Moderator (50)"), "powerLevel": 50});
                                        powerLevelModel.append({"text":  i18n("Admin (100)"), "powerLevel": 100});
                                    }
                                    currentIndex = indexOfValue(powerLevel)
                                }
                                onActivated: {
                                    room.setUserPowerLevel(userId, currentValue)
                                }
                            }
                        }
                    }
                }
                MobileForm.FormDelegateSeparator { below: userListSearchCard }
                MobileForm.AbstractFormDelegate {
                    id: userListSearchCard
                    Layout.fillWidth: true
                    visible: room.canSendState("m.room.power_levels")

                    contentItem: Kirigami.SearchField {
                        id: userListSearchField

                        autoAccept: false

                        Layout.fillWidth: true

                        Keys.onUpPressed: userListView.decrementCurrentIndex()
                        Keys.onDownPressed: userListView.incrementCurrentIndex()

                        onAccepted: {
                            let currentUser = userListView.itemAtIndex(userListView.currentIndex);
                            currentUser.action.trigger();
                        }
                    }
                    QQC2.Popup {
                        id: userListSearchPopup

                        x: userListSearchField.x
                        y: userListSearchField.y - height
                        width: userListSearchField.width
                        height: {
                            let maxHeight = userListSearchField.mapToGlobal(userListSearchField.x, userListSearchField.y).y - Kirigami.Units.largeSpacing * 3;
                            let minHeight = Kirigami.Units.gridUnit * 2 + userListSearchPopup.padding * 2;
                            let filterContentHeight = userListView.contentHeight + userListSearchPopup.padding * 2;

                            return Math.max(Math.min(filterContentHeight, maxHeight), minHeight);
                        }
                        padding: Kirigami.Units.smallSpacing
                        leftPadding: Kirigami.Units.smallSpacing / 2
                        rightPadding: Kirigami.Units.smallSpacing / 2
                        modal: false
                        onClosed: userListSearchField.text = ""

                        background: Kirigami.ShadowedRectangle {
                            property color borderColor: Kirigami.Theme.textColor

                            Kirigami.Theme.colorSet: Kirigami.Theme.View
                            Kirigami.Theme.inherit: false

                            radius: 4
                            color: Kirigami.Theme.backgroundColor

                            border {
                                color: Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0.3)
                                width: 1
                            }

                            shadow {
                                xOffset: 0
                                yOffset: 4
                                color: Qt.rgba(0, 0, 0, 0.3)
                                size: 8
                            }
                        }

                        contentItem: QQC2.ScrollView {
                            // HACK: Hide unnecessary horizontal scrollbar (https://bugreports.qt.io/browse/QTBUG-83890)
                            QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff

                            ListView {
                                id: userListView
                                clip: true

                                model: UserFilterModel {
                                    id: userListFilterModel
                                    sourceModel: userListModel
                                    filterText: userListSearchField.text

                                    onFilterTextChanged: {
                                        if (filterText.length > 0 && !userListSearchPopup.visible) {
                                            userListSearchPopup.open()
                                        } else if (filterText.length <= 0 && userListSearchPopup.visible) {
                                            userListSearchPopup.close()
                                        }
                                    }
                                }

                                delegate: Delegates.RoundedItemDelegate {
                                    id: userListItem

                                    required property string userId
                                    required property string avatar
                                    required property string name
                                    required property int powerLevel
                                    required property string powerLevelString

                                    text: name

                                    contentItem: RowLayout {
                                        KirigamiComponents.Avatar {
                                            Layout.preferredWidth: Kirigami.Units.iconSizes.medium
                                            Layout.preferredHeight: Kirigami.Units.iconSizes.medium
                                            source: userListItem.avatar ? ("image://" + userListItem.avatar) : ""
                                            name: userListItem.name
                                        }

                                        Delegates.SubtitleContentItem {
                                            itemDelegate: userListItem
                                            subtitle: userListItem.userId
                                            labelItem.textFormat: Text.PlainText
                                            subtitleItem.textFormat: Text.PlainText
                                            Layout.fillWidth: true
                                        }

                                        QQC2.Label {
                                            visible: userListItem.powerLevel > 0

                                            text: userListItem.powerLevelString
                                            color: Kirigami.Theme.disabledTextColor
                                            textFormat: Text.PlainText
                                            wrapMode: Text.NoWrap
                                        }
                                    }

                                    action: Kirigami.Action {
                                        id: editPowerLevelAction
                                        onTriggered: {
                                            userListSearchPopup.close()
                                            let dialog = powerLevelDialog.createObject(applicationWindow().overlay, {
                                                room: root.room,
                                                userId: userListItem.userId,
                                                powerLevel: userListItem.powerLevel
                                            });
                                            dialog.open();
                                        }
                                    }

                                    Component {
                                        id: powerLevelDialog
                                        PowerLevelDialog {
                                            id: powerLevelDialog
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        MobileForm.FormHeader {
            Layout.fillWidth: true
            visible: room.canSendState("m.room.power_levels")
            title: i18n("Default permissions")
        }
        MobileForm.FormCard {
            Layout.fillWidth: true
            visible: room.canSendState("m.room.power_levels")
            contentItem: ColumnLayout {
                spacing: 0
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Default user power level")
                    description: i18n("This is power level for all new users when joining the room")
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.defaultUserPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.defaultUserPowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Default power level to set the room state")
                    description: i18n("This is used for all state events that do not have their own entry here")
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.statePowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.statePowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Default power level to send messages")
                    description: i18n("This is used for all message events that do not have their own entry here")
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.defaultEventPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.defaultEventPowerLevel = currentValue
                }
            }
        }

        MobileForm.FormHeader {
            Layout.fillWidth: true
            visible: room.canSendState("m.room.power_levels")
            title: i18n("Basic permissions")
        }
        MobileForm.FormCard {
            Layout.fillWidth: true
            visible: room.canSendState("m.room.power_levels")
            contentItem: ColumnLayout {
                spacing: 0
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Invite users")
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.invitePowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.invitePowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Kick users")
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.kickPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.kickPowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Ban users")
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.banPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.banPowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Remove message sent by other users")
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.redactPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.redactPowerLevel = currentValue
                }
            }
        }

        MobileForm.FormHeader {
            Layout.fillWidth: true
            visible: room.canSendState("m.room.power_levels")
            title: i18n("Event permissions")
        }
        MobileForm.FormCard {
            Layout.fillWidth: true
            visible: room.canSendState("m.room.power_levels")
            contentItem: ColumnLayout {
                spacing: 0
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Change user permissions")
                    description: "m.room.power_levels"
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.powerLevelPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.powerLevelPowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Change the room name")
                    description: "m.room.name"
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.namePowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.namePowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Change the room avatar")
                    description: "m.room.avatar"
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.avatarPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.avatarPowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Change the room canonical alias")
                    description: "m.room.canonical_alias"
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.canonicalAliasPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.canonicalAliasPowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Change the room topic")
                    description: "m.room.topic"
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.topicPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.topicPowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Enable encryption for the room")
                    description: "m.room.encryption"
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.encryptionPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.encryptionPowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Change the room history visibility")
                    description: "m.room.history_visibility"
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.historyVisibilityPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.historyVisibilityPowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Set pinned events")
                    description: "m.room.pinned_events"
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.pinnedEventsPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.pinnedEventsPowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Upgrade the room")
                    description: "m.room.tombstone"
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.tombstonePowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.tombstonePowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Set the room server access control list (ACL)")
                    description: "m.room.server_acl"
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.serverAclPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.serverAclPowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    visible: room.isSpace
                    text: i18n("Set the children of this space")
                    description: "m.space.child"
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.spaceChildPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.spaceChildPowerLevel = currentValue
                }
                MobileForm.FormComboBoxDelegate {
                    text: i18n("Set the parent space of this room")
                    description: "m.space.parent"
                    textRole: "text"
                    valueRole: "powerLevel"
                    model: powerLevelModel
                    Component.onCompleted: currentIndex = indexOfValue(room.spaceChildPowerLevel)
                    onCurrentValueChanged: if(room.canSendState("m.room.power_levels")) room.spaceParentPowerLevel = currentValue
                }
            }
        }
    }
}
