pragma Singleton

import Quickshell
import Quickshell.Io
import QtQuick

Singleton {
    id: root

    property alias initialized: values.initialized
    property alias favorites: values.favorites
    property string saveError: ""

    FileView {
        id: preferencesFile

        path: Quickshell.stateDir + "/panama-home.json"
        blockLoading: true
        printErrors: false
        atomicWrites: true
        onSaved: root.saveError = ""
        onSaveFailed: error => root.saveError = "Could not save Home favorites."

        JsonAdapter {
            id: values

            property bool initialized: false
            property var favorites: []
        }
    }

    Connections {
        target: values
        function onInitializedChanged(): void { persistTimer.restart(); }
        function onFavoritesChanged(): void { persistTimer.restart(); }
    }

    Component.onCompleted: preferencesFile.reload()

    Timer {
        id: persistTimer
        interval: 180
        repeat: false
        onTriggered: preferencesFile.writeAdapter()
    }

    function cloneFavorites(): var {
        var clone = [];
        for (var index = 0; index < values.favorites.length; index++) {
            var favorite = values.favorites[index];
            clone.push({
                id: favorite.id,
                alias: favorite.alias
            });
        }
        return clone;
    }

    function isValidEntityId(entityId: var): bool {
        return typeof entityId === "string" && /^light\.[a-z0-9_]+$/.test(entityId);
    }

    function initialize(legacyIds: var): void {
        if (values.initialized) {
            return;
        }

        var seededFavorites = [];
        var seen = {};
        if (legacyIds && typeof legacyIds.length === "number") {
            for (var index = 0; index < legacyIds.length; index++) {
                var entityId = legacyIds[index];
                if (!isValidEntityId(entityId) || seen[entityId]) {
                    continue;
                }
                seen[entityId] = true;
                seededFavorites.push({ id: entityId, alias: "" });
            }
        }

        values.favorites = seededFavorites;
        values.initialized = true;
    }

    function resetHomeDefaults(): void {
        persistTimer.stop();
        values.favorites = [];
        values.initialized = false;
        root.saveError = "";
        preferencesFile.writeAdapter();
    }

    function isSelected(entityId: string): bool {
        for (var index = 0; index < values.favorites.length; index++) {
            if (values.favorites[index].id === entityId) {
                return true;
            }
        }
        return false;
    }

    function aliasFor(entityId: string, sourceName: string): string {
        for (var index = 0; index < values.favorites.length; index++) {
            var favorite = values.favorites[index];
            if (favorite.id === entityId && favorite.alias !== "") {
                return favorite.alias;
            }
        }
        return sourceName;
    }

    function add(entityId: string): void {
        if (!isValidEntityId(entityId) || isSelected(entityId)) {
            return;
        }

        var nextFavorites = cloneFavorites();
        nextFavorites.push({ id: entityId, alias: "" });
        values.favorites = nextFavorites;
    }

    function remove(entityId: string): void {
        var nextFavorites = [];
        var removed = false;
        for (var index = 0; index < values.favorites.length; index++) {
            var favorite = values.favorites[index];
            if (favorite.id === entityId) {
                removed = true;
                continue;
            }
            nextFavorites.push({ id: favorite.id, alias: favorite.alias });
        }
        if (removed) {
            values.favorites = nextFavorites;
        }
    }

    function setAlias(entityId: string, alias: string): void {
        var nextFavorites = cloneFavorites();
        var updated = false;
        var trimmedAlias = String(alias).trim();
        for (var index = 0; index < nextFavorites.length; index++) {
            if (nextFavorites[index].id === entityId) {
                nextFavorites[index] = { id: entityId, alias: trimmedAlias };
                updated = true;
                break;
            }
        }
        if (updated) {
            values.favorites = nextFavorites;
        }
    }

    function move(entityId: string, targetIndex: int): void {
        var nextFavorites = cloneFavorites();
        var currentIndex = -1;
        for (var index = 0; index < nextFavorites.length; index++) {
            if (nextFavorites[index].id === entityId) {
                currentIndex = index;
                break;
            }
        }
        if (currentIndex === -1) {
            return;
        }

        var favorite = nextFavorites.splice(currentIndex, 1)[0];
        var clampedIndex = Math.max(0, Math.min(targetIndex, nextFavorites.length));
        nextFavorites.splice(clampedIndex, 0, favorite);
        values.favorites = nextFavorites;
    }

    function retrySave(): void {
        preferencesFile.writeAdapter();
    }
}
