pragma ComponentBehavior: Bound

import QtQuick
import QtQuick.Controls 2.15

// Готовые сезонные сборки с сервера лаунчера: таблица со всем, что нужно
// решить, ставить её или нет, и одна кнопка, которая делает всё остальное —
// заводит сборку, ставит версию игры, модлоадер, Java и раскладывает файлы.
//
// Таблица собрана из Row фиксированных колонок, а не из TableView: в проекте
// нет ни одной модели QAbstractItemModel, а строки приходят готовыми
// QVariantMap — заводить ради семи колонок отдельную модель незачем.
Dialog {
    id: seasons

    required property var backend

    // Выбранная строка. Хранится по id, а не по индексу: список обновляется
    // под руками, и индекс после обновления указывал бы на другую сборку.
    property string selectedId: ""

    // Ширины колонок в одном месте: их повторяют и шапка, и делегат.
    readonly property var columns: [
        { key: "name",             title: qsTr("Название"),      width: 250, align: Text.AlignLeft },
        { key: "minecraftVersion", title: qsTr("Версия"),        width: 90,  align: Text.AlignLeft },
        { key: "loaderLabel",      title: qsTr("Загрузчик"),     width: 150, align: Text.AlignLeft },
        { key: "modCount",         title: qsTr("Модов"),         width: 70,  align: Text.AlignRight },
        { key: "seasonStart",      title: qsTr("Начало"),        width: 110, align: Text.AlignLeft },
        { key: "seasonEnd",        title: qsTr("Конец"),         width: 110, align: Text.AlignLeft },
        { key: "status",           title: qsTr("Статус"),        width: 140, align: Text.AlignLeft }
    ]

    modal: true
    padding: 0
    width: 960
    height: 560
    // Пока идёт установка, окно закрывается только кнопкой: случайный щелчок
    // мимо не должен спрятать единственную видимую отмену.
    closePolicy: seasons.backend.seasonalInstalling
                 ? Popup.NoAutoClose
                 : (Popup.CloseOnEscape | Popup.CloseOnPressOutside)

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

    // Строки приходят из C++ уже отсортированными и сведёнными с локальными
    // записями — здесь только показ.
    readonly property var entries: seasons.backend.seasonalCatalog

    readonly property var selectedEntry: {
        const list = seasons.entries
        for (var i = 0; i < list.length; ++i) {
            if (list[i].id === seasons.selectedId)
                return list[i]
        }
        return null
    }

    function openCatalog() {
        seasons.open()
    }

    function formatMb(bytes) {
        if (!bytes || bytes <= 0)
            return ""
        return (bytes / (1024 * 1024)).toFixed(1)
    }

    function cellText(entry, key) {
        if (key === "loaderLabel") {
            return entry.loaderVersion === ""
                    ? entry.loaderTitle
                    : entry.loaderTitle + " " + entry.loaderVersion
        }
        return String(entry[key])
    }

    // Свежий кэш отвечает без сети, поэтому дёргаем при каждом открытии.
    onAboutToShow: seasons.backend.refreshSeasonalCatalog(false)

    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: Item {

        // ── Шапка таблицы ───────────────────────────────────────────────
        Row {
            id: tableHeader
            anchors.top: parent.top
            anchors.left: parent.left
            anchors.leftMargin: 18
            height: 30

            Repeater {
                model: seasons.columns

                delegate: Text {
                    required property var modelData

                    width: modelData.width
                    height: tableHeader.height
                    text: modelData.title
                    color: "#aaaaaa"
                    font.pixelSize: 12
                    elide: Text.ElideRight
                    horizontalAlignment: modelData.align
                    verticalAlignment: Text.AlignVCenter
                    rightPadding: 10
                }
            }
        }

        Rectangle {
            id: headerLine
            anchors.top: tableHeader.bottom
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.leftMargin: 12
            anchors.rightMargin: 12
            height: 1
            color: "#333333"
        }

        // ── Сообщение вместо таблицы ────────────────────────────────────
        // Пустой список и ошибка выглядят одинаково пустыми, поэтому причина
        // показывается прямо на месте строк.
        Text {
            anchors.centerIn: parent
            width: parent.width - 80
            visible: seasons.entries.length === 0
            horizontalAlignment: Text.AlignHCenter
            wrapMode: Text.WordWrap
            color: seasons.backend.seasonalCatalogError === "" ? "#888888" : "#cc6666"
            font.pixelSize: 13
            text: seasons.backend.seasonalCatalogLoading
                      ? qsTr("Загрузка списка сборок…")
                      : (seasons.backend.seasonalCatalogError === ""
                             ? qsTr("Сборок пока нет")
                             : seasons.backend.seasonalCatalogError)
        }

        // ── Строки ──────────────────────────────────────────────────────
        ListView {
            id: buildList
            anchors.top: headerLine.bottom
            anchors.topMargin: 4
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.bottom: parent.bottom
            anchors.leftMargin: 12
            anchors.rightMargin: 12
            clip: true
            spacing: 1
            model: seasons.entries
            ScrollIndicator.vertical: ScrollIndicator {}

            delegate: Rectangle {
                id: buildRow
                required property var modelData

                width: buildList.width
                height: 36
                radius: 4
                color: seasons.selectedId === buildRow.modelData.id ? "#91B315"
                     : rowArea.containsMouse ? "#2d2d2d" : "transparent"

                readonly property bool highlighted: seasons.selectedId === buildRow.modelData.id

                Row {
                    anchors.left: parent.left
                    anchors.leftMargin: 6
                    anchors.verticalCenter: parent.verticalCenter

                    Repeater {
                        model: seasons.columns

                        delegate: Text {
                            required property var modelData

                            width: modelData.width
                            text: seasons.cellText(buildRow.modelData, modelData.key)
                            // Подсвеченная строка залита зелёным — тёмный текст
                            // на ней читается, светлый нет.
                            color: buildRow.highlighted
                                       ? "#1e1e1e"
                                       : (modelData.key === "status"
                                              && buildRow.modelData.updateAvailable
                                                  ? "#91B315" : "#ffffff")
                            font.pixelSize: 13
                            elide: Text.ElideRight
                            horizontalAlignment: modelData.align
                            rightPadding: 10
                        }
                    }
                }

                MouseArea {
                    id: rowArea
                    anchors.fill: parent
                    hoverEnabled: true
                    onClicked: seasons.selectedId = buildRow.modelData.id
                    onDoubleClicked: {
                        seasons.selectedId = buildRow.modelData.id
                        seasons.installSelected()
                    }
                }
            }
        }
    }

    function installSelected() {
        const entry = seasons.selectedEntry
        if (!entry || seasons.backend.busy)
            return
        seasons.backend.installSeasonalBuild(entry.id)
    }

    footer: Item {
        implicitHeight: 76

        Rectangle {
            anchors.top: parent.top
            width: parent.width
            height: 1
            color: "#333333"
        }

        // Описание и размер выбранной сборки: они длинные и в таблицу не
        // помещаются, а решение принимается по ним.
        Column {
            anchors.left: parent.left
            anchors.leftMargin: 18
            anchors.right: footerButtons.left
            anchors.rightMargin: 12
            anchors.verticalCenter: parent.verticalCenter
            spacing: 3

            Text {
                width: parent.width
                elide: Text.ElideRight
                color: "#ffffff"
                font.pixelSize: 12
                text: seasons.selectedEntry ? seasons.selectedEntry.description : ""
            }

            Text {
                width: parent.width
                elide: Text.ElideRight
                color: "#888888"
                font.pixelSize: 11
                text: {
                    if (!seasons.selectedEntry)
                        return qsTr("Выберите сборку в списке")
                    const entry = seasons.selectedEntry
                    var line = qsTr("Ревизия %1").arg(entry.revision)
                    const size = seasons.formatMb(entry.sizeBytes)
                    if (size !== "")
                        line += qsTr(" · %1 МБ").arg(size)
                    if (entry.serverUrl !== "")
                        line += " · " + entry.serverUrl
                    if (entry.updateAvailable)
                        line += qsTr(" · установлена ревизия %1").arg(entry.installedRevision)
                    return line
                }
            }
        }

        Row {
            id: footerButtons
            anchors.right: parent.right
            anchors.rightMargin: 18
            anchors.verticalCenter: parent.verticalCenter
            spacing: 12

            Button {
                id: refreshButton
                width: 150
                height: 36
                enabled: !seasons.backend.seasonalCatalogLoading
                contentItem: Text {
                    text: seasons.backend.seasonalCatalogLoading ? qsTr("Обновление…")
                                                                 : qsTr("Обновить список")
                    color: refreshButton.enabled ? "#ffffff" : "#888888"
                    font.pixelSize: 13
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                }
                background: Rectangle {
                    color: refreshButton.pressed ? "#444444" : "#333333"
                    radius: 6
                }
                onClicked: seasons.backend.refreshSeasonalCatalog(true)
            }

            Button {
                id: installButton
                width: 150
                height: 36
                // Установка занимает и панель загрузки, и .minecraft целиком:
                // пока лаунчер занят чем угодно, вторую начинать нельзя.
                enabled: seasons.selectedEntry !== null && !seasons.backend.busy
                contentItem: Text {
                    text: seasons.selectedEntry && seasons.selectedEntry.updateAvailable
                              ? qsTr("Обновить")
                              : qsTr("Установить")
                    color: installButton.enabled ? "#ffffff" : "#888888"
                    font.pixelSize: 13
                    font.bold: true
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                }
                background: Rectangle {
                    color: !installButton.enabled ? "#2a2a2a"
                         : installButton.pressed ? "#6a8510" : "#91B315"
                    radius: 6
                }
                onClicked: seasons.installSelected()
            }
        }
    }
}
