pragma ComponentBehavior: Bound

import QtQuick
import QtQuick.Controls 2.15
import QtQuick.Layouts 2.15

// Пользовательские сборки одним окном: слева список со сменой активной,
// справа карточка выбранной — имя, сервер, версия Minecraft и модлоадеры.
//
// Карточка сохраняет правки по ходу редактирования, отдельной кнопки
// «Сохранить» нет: иначе появляется неочевидное несохранённое состояние,
// пока пользователь переключается между сборками в левом списке.
Dialog {
    id: buildsDialog

    required property var backend

    // Сборка, открытая в карточке справа. С активной не связана: активную
    // меняет отдельная кнопка, чтобы случайный клик по списку не запускал
    // архивацию .minecraft.
    property int editIndex: -1
    // Пока карточка заполняется, обработчики полей не должны писать обратно.
    property bool loading: false

    modal: true
    padding: 0
    width: 880
    height: 600
    closePolicy: buildsDialog.backend.switching ? Popup.NoAutoClose
                                                : Popup.CloseOnEscape | Popup.CloseOnPressOutside

    background: Rectangle {
        color: "#1e1e1e"
        radius: 10
        border.color: "#91B315"
        border.width: 1
    }

    function selectBuild(index) {
        const data = buildsDialog.backend.customBuildAt(index)
        buildsDialog.loading = true
        buildsDialog.editIndex = index
        bdName.text = data.name || ""
        bdServer.text = data.serverUrl || ""
        bdMinecraft.selectedId = data.minecraftVersion || ""
        loaderPanel.applyBuild(data.loader || "", data.loaderVersion || "")
        buildsDialog.loading = false
        buildsDialog.refreshStatus()
    }

    // Удаление необратимо и уносит с собой архив сборки, поэтому сначала
    // спрашиваем. Индекс запоминаем здесь: к моменту ответа строка списка под
    // курсором может быть уже другой.
    function askRemove(index) {
        const info = buildsDialog.backend.customBuildRemovalInfo(index)
        if (!info || info.name === undefined)
            return
        removeConfirm.buildIndex = index
        removeConfirm.buildName = info.name
        removeConfirm.hasArchive = info.hasArchive === true
        removeConfirm.active = info.active === true
        removeConfirm.lastOne = info.lastOne === true
        removeConfirm.open()
    }

    function performRemove(index) {
        buildsDialog.backend.removeCustomBuild(index)
        const left = buildsDialog.backend.customBuildNames.length
        if (left === 0)
            buildsDialog.editIndex = -1
        else
            buildsDialog.selectBuild(Math.min(index, left - 1))
    }

    function commit(fields) {
        if (buildsDialog.loading || buildsDialog.editIndex < 0)
            return
        buildsDialog.backend.updateCustomBuild(buildsDialog.editIndex, fields)
        buildsDialog.refreshStatus()
    }

    function refreshStatus() {
        if (buildsDialog.editIndex < 0) {
            bdStatus.text = ""
            return
        }
        const problems = buildsDialog.backend.checkInstallation(buildsDialog.editIndex)
        bdStatus.ok = problems.length === 0
        bdStatus.text = problems.length === 0
                ? qsTr("Всё на месте, сборку можно запускать")
                : qsTr("Не хватает файлов (%1): %2").arg(problems.length).arg(problems[0])
    }

    function newBuildName() {
        const taken = buildsDialog.backend.customBuildNames
        for (var n = 1; ; ++n) {
            const candidate = qsTr("Сборка %1").arg(n)
            if (taken.indexOf(candidate) === -1)
                return candidate
        }
    }

    Dialog {
        id: removeConfirm

        property int buildIndex: -1
        property string buildName: ""
        property bool hasArchive: false
        property bool active: false
        property bool lastOne: false

        modal: true
        padding: 0
        width: 420
        parent: buildsDialog.parent
        x: (buildsDialog.parent.width  - width)  / 2
        y: (buildsDialog.parent.height - height) / 2
        closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside

        background: Rectangle {
            color: "#1e1e1e"
            radius: 10
            border.color: "#cc6666"
            border.width: 1
        }

        header: Item {
            implicitHeight: 52
            Text {
                anchors.centerIn: parent
                text: qsTr("Удалить сборку?")
                color: "#ffffff"
                font.pixelSize: 17
                font.bold: true
            }
            Rectangle {
                anchors.bottom: parent.bottom
                width: parent.width
                height: 1
                color: "#333333"
            }
        }

        contentItem: Column {
            spacing: 10
            topPadding: 18
            bottomPadding: 18

            Text {
                x: 20
                width: parent.width - 40
                wrapMode: Text.Wrap
                color: "#ffffff"
                font.pixelSize: 13
                text: qsTr("Сборка «%1» будет удалена без возможности восстановления.")
                          .arg(removeConfirm.buildName)
            }

            Text {
                x: 20
                width: parent.width - 40
                visible: removeConfirm.hasArchive
                wrapMode: Text.Wrap
                color: "#cc6666"
                font.pixelSize: 12
                text: qsTr("Вместе с ней удалится её архив: моды, конфиги и миры этой сборки восстановить будет нельзя.")
            }

            Text {
                x: 20
                width: parent.width - 40
                visible: removeConfirm.active && !removeConfirm.lastOne
                wrapMode: Text.Wrap
                color: "#cc6666"
                font.pixelSize: 12
                text: qsTr("Сборка сейчас активна: содержимое .minecraft принадлежит ей и будет очищено, а на его место развернётся следующая сборка.")
            }

            Text {
                x: 20
                width: parent.width - 40
                visible: removeConfirm.lastOne
                wrapMode: Text.Wrap
                color: "#888888"
                font.pixelSize: 12
                text: qsTr("Это последняя сборка. Содержимое .minecraft останется на месте.")
            }
        }

        footer: Item {
            implicitHeight: 60
            Rectangle {
                anchors.top: parent.top
                width: parent.width
                height: 1
                color: "#333333"
            }
            Row {
                anchors.centerIn: parent
                spacing: 12

                Button {
                    text: qsTr("Отмена")
                    width: 130; height: 36
                    contentItem: Text {
                        text: parent.text
                        color: "#ffffff"
                        horizontalAlignment: Text.AlignHCenter
                        verticalAlignment: Text.AlignVCenter
                    }
                    background: Rectangle {
                        color: parent.pressed ? "#6a8510" : "#91B315"
                        radius: 6
                    }
                    onClicked: removeConfirm.close()
                }

                Button {
                    text: qsTr("Удалить")
                    width: 130; height: 36
                    contentItem: Text {
                        text: parent.text
                        color: "#ffffff"
                        horizontalAlignment: Text.AlignHCenter
                        verticalAlignment: Text.AlignVCenter
                    }
                    background: Rectangle {
                        color: parent.pressed ? "#8a3a3a" : "#663333"
                        radius: 6
                        border.color: "#cc6666"
                        border.width: 1
                    }
                    onClicked: {
                        const index = removeConfirm.buildIndex
                        removeConfirm.close()
                        buildsDialog.performRemove(index)
                    }
                }
            }
        }

        onClosed: removeConfirm.buildIndex = -1
    }

    VersionPickerDialog {
        id: versionPicker
        backend: buildsDialog.backend
        parent: buildsDialog.parent
        x: (buildsDialog.parent.width  - width)  / 2
        y: (buildsDialog.parent.height - height) / 2
        onVersionChosen: (versionId) => bdMinecraft.selectedId = versionId
    }

    // Установка версии или модлоадера меняет комплектность сборки — строка
    // состояния должна это заметить, не дожидаясь переоткрытия окна.
    Connections {
        target: buildsDialog.backend
        function onInstalledVersionsChanged() { buildsDialog.refreshStatus() }
    }

    onAboutToShow: {
        buildsDialog.backend.refreshVersionCatalog()
        const names = buildsDialog.backend.customBuildNames
        if (names.length === 0)
            buildsDialog.editIndex = -1
        else
            buildsDialog.selectBuild(Math.max(0, buildsDialog.backend.activeBuildIndex))
    }

    header: Item {
        implicitHeight: 52
        Text {
            anchors.centerIn: parent
            text: qsTr("Пользовательские сборки")
            color: "#ffffff"
            font.pixelSize: 17
            font.bold: true
        }
        Rectangle {
            anchors.bottom: parent.bottom
            width: parent.width
            height: 1
            color: "#333333"
        }
    }

    contentItem: RowLayout {
        spacing: 0

        // ── Список сборок ───────────────────────────────────────────────
        Item {
            Layout.preferredWidth: 260
            Layout.fillHeight: true
            enabled: !buildsDialog.backend.switching

            ListView {
                id: buildList
                anchors.top: parent.top
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.bottom: addBuildRow.top
                anchors.margins: 8
                clip: true
                spacing: 2
                model: buildsDialog.backend.customBuildNames

                delegate: ItemDelegate {
                    id: buildRow
                    required property string modelData
                    required property int index

                    width: buildList.width
                    height: 40

                    contentItem: Item {
                        Text {
                            anchors.left: parent.left
                            anchors.leftMargin: 8
                            anchors.right: activeBadge.left
                            anchors.rightMargin: 6
                            anchors.verticalCenter: parent.verticalCenter
                            text: buildRow.modelData
                            color: "#ffffff"
                            elide: Text.ElideRight
                            font.pixelSize: 13
                        }
                        Text {
                            id: activeBadge
                            anchors.right: buildTrash.left
                            anchors.rightMargin: 8
                            anchors.verticalCenter: parent.verticalCenter
                            visible: buildRow.index === buildsDialog.backend.activeBuildIndex
                            text: qsTr("активна")
                            color: "#91B315"
                            font.pixelSize: 10
                        }
                        Image {
                            id: buildTrash
                            width: 16; height: 16
                            anchors.right: parent.right
                            anchors.rightMargin: 8
                            anchors.verticalCenter: parent.verticalCenter
                            visible: buildRow.hovered
                            opacity: buildTrashArea.containsMouse ? 1.0 : 0.7
                            source: "images/Trash.svg"
                            sourceSize.width: 16; sourceSize.height: 16
                            fillMode: Image.PreserveAspectFit

                            MouseArea {
                                id: buildTrashArea
                                anchors.fill: parent
                                anchors.margins: -6
                                hoverEnabled: true
                                onClicked: buildsDialog.askRemove(buildRow.index)
                            }
                        }
                    }

                    background: Rectangle {
                        color: (buildsDialog.editIndex === buildRow.index || buildRow.hovered)
                               ? "#91B315" : "#232323"
                        radius: 5
                    }

                    onClicked: buildsDialog.selectBuild(buildRow.index)
                }

                ScrollIndicator.vertical: ScrollIndicator {}
            }

            Rectangle {
                id: addBuildRow
                anchors.bottom: parent.bottom
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.margins: 8
                height: 34
                radius: 5
                color: addBuildArea.containsPress ? "#2d2d2d" : "transparent"

                Text {
                    anchors.centerIn: parent
                    text: qsTr("+ Новая сборка")
                    color: "#91B315"
                    font.pixelSize: 12
                }

                MouseArea {
                    id: addBuildArea
                    anchors.fill: parent
                    onClicked: {
                        buildsDialog.backend.addCustomBuild(buildsDialog.newBuildName(), "", "")
                        buildsDialog.selectBuild(buildsDialog.backend.customBuildNames.length - 1)
                    }
                }
            }
        }

        Rectangle {
            Layout.preferredWidth: 1
            Layout.fillHeight: true
            color: "#333333"
        }

        // ── Карточка выбранной сборки ───────────────────────────────────
        Item {
            Layout.fillWidth: true
            Layout.fillHeight: true
            enabled: buildsDialog.editIndex >= 0 && !buildsDialog.backend.switching
            opacity: enabled ? 1.0 : 0.4

            Flickable {
                anchors.fill: parent
                anchors.margins: 20
                contentHeight: detailsColumn.height
                clip: true
                boundsBehavior: Flickable.StopAtBounds
                ScrollIndicator.vertical: ScrollIndicator {}

            Column {
                id: detailsColumn
                width: parent.width
                spacing: 12

                LabelledField {
                    id: bdName
                    width: parent.width
                    label: qsTr("Название сборки")
                    placeholder: qsTr("как её видно в списке")
                    onEditingFinished: buildsDialog.commit({"name": bdName.text.trim()})
                }

                LabelledField {
                    id: bdServer
                    width: parent.width
                    label: qsTr("Адрес сервера")
                    placeholder: qsTr("host:port (необязательно)")
                    onEditingFinished: buildsDialog.commit({"serverUrl": bdServer.text.trim()})
                }

                Text {
                    text: qsTr("Версия Minecraft")
                    color: "#aaaaaa"
                    font.pixelSize: 11
                }

                // Само поле только показывает выбор: версий около тысячи, и
                // разбираться в них удобнее в отдельном окне с категориями.
                Rectangle {
                    id: bdMinecraft
                    property string selectedId: ""

                    width: parent.width
                    height: 36
                    radius: 6
                    color: "#2a2a2a"
                    border.color: versionFieldArea.containsMouse ? "#91B315" : "#444444"
                    border.width: 1

                    Text {
                        anchors.fill: parent
                        leftPadding: 10
                        rightPadding: 110
                        verticalAlignment: Text.AlignVCenter
                        elide: Text.ElideRight
                        color: bdMinecraft.selectedId === "" ? "#666666" : "#ffffff"
                        text: bdMinecraft.selectedId === "" ? qsTr("Выберите версию")
                                                            : bdMinecraft.selectedId
                    }

                    Text {
                        anchors.right: parent.right
                        anchors.rightMargin: 12
                        anchors.verticalCenter: parent.verticalCenter
                        text: qsTr("Выбрать…")
                        color: "#91B315"
                        font.pixelSize: 12
                    }

                    MouseArea {
                        id: versionFieldArea
                        anchors.fill: parent
                        hoverEnabled: true
                        onClicked: versionPicker.openFor(bdMinecraft.selectedId)
                    }

                    onSelectedIdChanged: buildsDialog.commit({"minecraftVersion":
                                                              bdMinecraft.selectedId})
                }

                Text {
                    text: qsTr("Модлоадер")
                    color: "#aaaaaa"
                    font.pixelSize: 11
                }

                // Лоадеры несовместимы между собой: игра запускается ровно с
                // одним профилем versions/<id>. Поэтому отметка одного снимает
                // остальные, а «ничего не отмечено» — это чистая ваниль.
                Column {
                    id: loaderPanel
                    width: parent.width
                    spacing: 8

                    property var rows: [bdForge, bdFabric, bdNeoForge, bdQuilt]

                    function applyBuild(loader, loaderVersion) {
                        for (var i = 0; i < loaderPanel.rows.length; ++i)
                            loaderPanel.rows[i].applyBuild(loader, loaderVersion)
                    }

                    function selectedRow() {
                        for (var i = 0; i < loaderPanel.rows.length; ++i) {
                            if (loaderPanel.rows[i].checked)
                                return loaderPanel.rows[i]
                        }
                        return null
                    }

                    function keepOnly(row) {
                        for (var i = 0; i < loaderPanel.rows.length; ++i) {
                            if (loaderPanel.rows[i] === row)
                                continue
                            loaderPanel.rows[i].applyBuild("", "")
                        }
                    }

                    function commitSelection() {
                        const row = loaderPanel.selectedRow()
                        buildsDialog.commit({
                            "loader": row ? row.loaderKey : "",
                            "loaderVersion": row ? row.selectedVersion : "",
                            // Профиль появится только после установки: пока
                            // сборка запускается на чистой ванили.
                            "resolvedVersionId": ""
                        })
                    }

                    LoaderRow {
                        id: bdForge
                        width: parent.width
                        backend: buildsDialog.backend
                        loaderKey: "forge"
                        title: qsTr("Minecraft Forge")
                        gameVersion: bdMinecraft.selectedId
                        onUserChecked: loaderPanel.keepOnly(bdForge)
                        onChanged: loaderPanel.commitSelection()
                    }
                    LoaderRow {
                        id: bdFabric
                        width: parent.width
                        backend: buildsDialog.backend
                        loaderKey: "fabric"
                        title: qsTr("Fabric Loader")
                        gameVersion: bdMinecraft.selectedId
                        onUserChecked: loaderPanel.keepOnly(bdFabric)
                        onChanged: loaderPanel.commitSelection()
                    }
                    LoaderRow {
                        id: bdNeoForge
                        width: parent.width
                        backend: buildsDialog.backend
                        loaderKey: "neoforge"
                        title: qsTr("NeoForge")
                        gameVersion: bdMinecraft.selectedId
                        onUserChecked: loaderPanel.keepOnly(bdNeoForge)
                        onChanged: loaderPanel.commitSelection()
                    }
                    LoaderRow {
                        id: bdQuilt
                        width: parent.width
                        backend: buildsDialog.backend
                        loaderKey: "quilt"
                        title: qsTr("Quilt Loader")
                        gameVersion: bdMinecraft.selectedId
                        onUserChecked: loaderPanel.keepOnly(bdQuilt)
                        onChanged: loaderPanel.commitSelection()
                    }
                }

                Text {
                    id: bdStatus
                    property bool ok: false
                    width: parent.width
                    color: bdStatus.ok ? "#8fbf5a" : "#cc6666"
                    font.pixelSize: 11
                    wrapMode: Text.Wrap
                }
            }
            }
        }
    }

    footer: Item {
        implicitHeight: 60
        Rectangle {
            anchors.top: parent.top
            width: parent.width
            height: 1
            color: "#333333"
        }
        Row {
            anchors.centerIn: parent
            spacing: 12

            Button {
                text: qsTr("Установить")
                width: 140; height: 36
                enabled: buildsDialog.editIndex >= 0 && !buildsDialog.backend.busy
                opacity: enabled ? 1.0 : 0.45
                contentItem: Text {
                    text: parent.text
                    color: "#ffffff"
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                }
                background: Rectangle {
                    color: parent.pressed ? "#444444" : "#333333"
                    radius: 6
                }
                onClicked: buildsDialog.backend.installCustomBuild(buildsDialog.editIndex)
            }

            Button {
                text: qsTr("Сделать активной")
                width: 170; height: 36
                enabled: buildsDialog.editIndex >= 0
                         && buildsDialog.editIndex !== buildsDialog.backend.activeBuildIndex
                         && !buildsDialog.backend.busy
                opacity: enabled ? 1.0 : 0.45
                contentItem: Text {
                    text: parent.text
                    color: "#ffffff"
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                }
                background: Rectangle {
                    color: parent.pressed ? "#6a8510" : "#91B315"
                    radius: 6
                }
                onClicked: buildsDialog.backend.activeBuildIndex = buildsDialog.editIndex
            }

            Button {
                text: qsTr("Закрыть")
                width: 120; height: 36
                enabled: !buildsDialog.backend.switching
                opacity: enabled ? 1.0 : 0.45
                contentItem: Text {
                    text: parent.text
                    color: "#ffffff"
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                }
                background: Rectangle {
                    color: parent.pressed ? "#444444" : "#333333"
                    radius: 6
                }
                onClicked: buildsDialog.close()
            }
        }
    }
}
