import QtQuick
import QtQuick.Controls 2.15

// Один модлоадер в карточке сборки: чекбокс и, когда он отмечен, список версий
// именно под выбранную версию Minecraft.
//
// Совместимость проверять не нужно: backend.loaderVersions() отдаёт список уже
// под конкретную версию игры, поэтому несовместимой строки в нём не бывает.
// Пустой список — это «лоадер не поддерживает эту версию игры», и он тоже
// показывается словами, а не пустым выпадающим списком.
Column {
    id: loaderRow

    required property var backend
    required property string loaderKey
    required property string title

    // Версия Minecraft, выбранная в карточке. Её смена сбрасывает выбор.
    property string gameVersion: ""

    property alias checked: box.checked
    property string selectedVersion: ""
    property var entries: []

    // Пользователь щёлкнул чекбокс — карточка снимет отметки с остальных
    // лоадеров: одновременно в .minecraft может жить только один.
    signal userChecked()
    // Отметка или версия изменились — карточке пора сохранить сборку.
    signal changed()

    // Ставится, пока карточка заполняет строку данными сборки: в это время
    // обработчики не должны считать изменения пользовательскими.
    property bool applying: false

    spacing: 4

    function versionIndex(version) {
        for (var i = 0; i < loaderRow.entries.length; ++i) {
            if (loaderRow.entries[i].version === version)
                return i
        }
        return -1
    }

    // Единственное место, где меняются entries и selectedVersion. Через него
    // проходят все три пути — кэш, ответ сети и заполнение из сборки, — потому
    // что выбранная версия обязана существовать в списке под текущую версию
    // игры. Раньше проверял только путь из сети, и версия лоадера от прошлой
    // версии игры доживала до сохранения сборки.
    function applyEntries(list) {
        loaderRow.entries = list

        // Список отсортирован новыми вперёд, поэтому максимально доступная
        // версия для этой версии игры — всегда первая строка.
        if (loaderRow.versionIndex(loaderRow.selectedVersion) < 0) {
            const fallback = list.length > 0 ? list[0].version : ""
            const changedValue = loaderRow.selectedVersion !== fallback
            loaderRow.selectedVersion = fallback
            if (changedValue && !loaderRow.applying)
                loaderRow.changed()
        }

        combo.currentIndex = loaderRow.versionIndex(loaderRow.selectedVersion)
    }

    function reload() {
        if (!box.checked || loaderRow.gameVersion === "") {
            loaderRow.applyEntries([])
            return
        }
        // Сначала из кэша — список появляется мгновенно, — потом обновление сети.
        loaderRow.applyEntries(loaderRow.backend.loaderVersions(loaderRow.loaderKey,
                                                                loaderRow.gameVersion))
        loaderRow.backend.refreshLoaderVersions(loaderRow.loaderKey, loaderRow.gameVersion)
    }

    // Заполнение из сохранённой сборки: без сигналов changed().
    function applyBuild(loader, loaderVersion) {
        loaderRow.applying = true
        box.checked = loader === loaderRow.loaderKey
        // Версию из сборки берём как пожелание: если под выбранную версию игры
        // её нет, applyEntries() заменит её на максимально доступную.
        loaderRow.selectedVersion = box.checked ? loaderVersion : ""
        loaderRow.reload()
        loaderRow.applying = false
    }

    onGameVersionChanged: {
        // Сборка лоадера привязана к версии игры: под новой версией прежний
        // выбор недействителен, и список перезапрашивается заново.
        loaderRow.selectedVersion = ""
        loaderRow.reload()
    }

    Connections {
        target: loaderRow.backend
        function onLoaderVersionsChanged(key, game) {
            if (key !== loaderRow.loaderKey || game !== loaderRow.gameVersion || !box.checked)
                return
            loaderRow.applyEntries(loaderRow.backend.loaderVersions(key, game))
        }
    }

    CheckBox {
        id: box
        text: loaderRow.title
        enabled: loaderRow.gameVersion !== ""

        indicator: Rectangle {
            implicitWidth: 18
            implicitHeight: 18
            x: 0
            y: (box.height - height) / 2
            radius: 4
            color: box.checked ? "#91B315" : "#2a2a2a"
            border.color: box.checked ? "#91B315" : "#444444"
            border.width: 1

            Text {
                anchors.centerIn: parent
                visible: box.checked
                text: "✓"
                color: "#1e1e1e"
                font.pixelSize: 13
                font.bold: true
            }
        }

        contentItem: Text {
            leftPadding: box.indicator.width + 8
            text: box.text
            color: box.enabled ? "#ffffff" : "#666666"
            font.pixelSize: 12
            verticalAlignment: Text.AlignVCenter
        }

        onToggled: {
            if (box.checked)
                loaderRow.userChecked()
            else
                loaderRow.selectedVersion = ""
            loaderRow.reload()
            loaderRow.changed()
        }
    }

    DarkCombo {
        id: combo
        visible: box.checked && loaderRow.entries.length > 0
        width: loaderRow.width - 26
        height: 32
        x: 26
        model: loaderRow.entries.map(entry => entry.label)

        onActivated: (index) => {
            if (index < 0 || index >= loaderRow.entries.length)
                return
            loaderRow.selectedVersion = loaderRow.entries[index].version
            loaderRow.changed()
        }
    }

    Text {
        visible: box.checked && loaderRow.entries.length === 0
        x: 26
        width: loaderRow.width - 26
        wrapMode: Text.Wrap
        font.pixelSize: 11
        color: loaderRow.backend.loaderVersionsLoading(loaderRow.loaderKey, loaderRow.gameVersion)
               ? "#888888" : "#cc6666"
        text: loaderRow.backend.loaderVersionsLoading(loaderRow.loaderKey, loaderRow.gameVersion)
              ? qsTr("Загрузка списка версий %1…").arg(loaderRow.title)
              : qsTr("%1 не поддерживает Minecraft %2").arg(loaderRow.title)
                                                       .arg(loaderRow.gameVersion)
    }
}
