import QtQuick
import qs.Common

Item {
    id: root

    property var widgetsModel: null
    property var components: null
    property bool noBackground: false
    required property var axis
    property string section: "center"
    property var parentScreen: null
    property real widgetThickness: 30
    property real barThickness: 48
    property real barSpacing: 4
    property var barConfig: null
    property var blurBarWindow: null
    property real sectionAvailablePrimarySize: 0
    property bool overrideAxisLayout: false
    property bool forceVerticalLayout: false

    readonly property bool isVertical: overrideAxisLayout ? forceVerticalLayout : (axis?.isVertical ?? false)
    readonly property real widgetSpacing: {
        const baseSpacing = noBackground ? 2 : Theme.spacingXS;
        const outlineThickness = (barConfig?.widgetOutlineEnabled ?? false) ? (barConfig?.widgetOutlineThickness ?? 1) : 0;
        return baseSpacing + (outlineThickness * 2);
    }

    property var centerWidgets: []
    property int totalWidgets: 0
    property real totalSize: 0
    property real contentStart: 0
    property real contentSize: 0

    function updateLayout() {
        if (SettingsData.centeringMode === "geometric") {
            applyGeometricLayout();
        } else {
            applyIndexLayout();
        }
        updateContentExtent();
    }

    function updateContentExtent() {
        if (centerWidgets.length === 0) {
            contentStart = 0;
            contentSize = 0;
            return;
        }
        let start = Infinity;
        let end = -Infinity;
        for (const widget of centerWidgets) {
            const pos = isVertical ? widget.y : widget.x;
            const size = isVertical ? widget.height : widget.width;
            start = Math.min(start, pos);
            end = Math.max(end, pos + size);
        }
        contentStart = start;
        contentSize = end - start;
    }

    function applyGeometricLayout() {
        if ((isVertical ? height : width) <= 0 || !visible)
            return;

        centerWidgets = [];
        totalWidgets = 0;
        totalSize = 0;

        for (var i = 0; i < centerRepeater.count; i++) {
            const loader = centerRepeater.itemAt(i);
            if (loader && loader.active && loader.item && loader.item.visible) {
                centerWidgets.push(loader.item);
                totalWidgets++;
                totalSize += isVertical ? loader.item.height : loader.item.width;
            }
        }

        if (totalWidgets === 0)
            return;

        if (totalWidgets > 1)
            totalSize += widgetSpacing * (totalWidgets - 1);

        positionWidgetsGeometric();
    }

    function positionWidgetsGeometric() {
        const parentLength = isVertical ? height : width;
        const parentCenter = parentLength / 2;
        let currentPos = parentCenter - (totalSize / 2);

        centerWidgets.forEach(widget => {
            if (isVertical) {
                widget.anchors.verticalCenter = undefined;
                widget.y = currentPos;
            } else {
                widget.anchors.horizontalCenter = undefined;
                widget.x = currentPos;
            }
            const widgetSize = isVertical ? widget.height : widget.width;
            currentPos += widgetSize + widgetSpacing;
        });
    }

    function applyIndexLayout() {
        if ((isVertical ? height : width) <= 0 || !visible)
            return;

        centerWidgets = [];
        totalWidgets = 0;
        totalSize = 0;

        let configuredMiddleWidget = null;
        let configuredLeftWidget = null;
        let configuredRightWidget = null;

        const configuredWidgets = centerRepeater.count;
        const isOddConfigured = configuredWidgets % 2 === 1;
        const configuredMiddlePos = Math.floor(configuredWidgets / 2);
        const configuredLeftPos = isOddConfigured ? -1 : ((configuredWidgets / 2) - 1);
        const configuredRightPos = isOddConfigured ? -1 : (configuredWidgets / 2);

        for (var i = 0; i < centerRepeater.count; i++) {
            const wrapper = centerRepeater.itemAt(i);
            if (!wrapper)
                continue;

            if (isOddConfigured && i === configuredMiddlePos && wrapper.active && wrapper.item && wrapper.item.visible)
                configuredMiddleWidget = wrapper.item;
            if (!isOddConfigured && i === configuredLeftPos && wrapper.active && wrapper.item && wrapper.item.visible)
                configuredLeftWidget = wrapper.item;
            if (!isOddConfigured && i === configuredRightPos && wrapper.active && wrapper.item && wrapper.item.visible)
                configuredRightWidget = wrapper.item;

            if (wrapper.active && wrapper.item && wrapper.item.visible) {
                centerWidgets.push(wrapper.item);
                totalWidgets++;
                totalSize += isVertical ? wrapper.item.height : wrapper.item.width;
            }
        }

        if (totalWidgets === 0)
            return;

        if (totalWidgets > 1)
            totalSize += widgetSpacing * (totalWidgets - 1);

        positionWidgetsByIndex(configuredWidgets, configuredMiddleWidget, configuredLeftWidget, configuredRightWidget);
    }

    function positionWidgetsByIndex(configuredWidgets, configuredMiddleWidget, configuredLeftWidget, configuredRightWidget) {
        const parentCenter = (isVertical ? height : width) / 2;
        const isOddConfigured = configuredWidgets % 2 === 1;

        centerWidgets.forEach(widget => {
            if (isVertical)
                widget.anchors.verticalCenter = undefined;
            else
                widget.anchors.horizontalCenter = undefined;
        });

        if (isOddConfigured && configuredMiddleWidget) {
            const middleWidget = configuredMiddleWidget;
            const middleIndex = centerWidgets.indexOf(middleWidget);
            const middleSize = isVertical ? middleWidget.height : middleWidget.width;

            if (isVertical)
                middleWidget.y = parentCenter - (middleSize / 2);
            else
                middleWidget.x = parentCenter - (middleSize / 2);

            let currentPos = isVertical ? middleWidget.y : middleWidget.x;
            for (var i = middleIndex - 1; i >= 0; i--) {
                const size = isVertical ? centerWidgets[i].height : centerWidgets[i].width;
                currentPos -= (widgetSpacing + size);
                if (isVertical)
                    centerWidgets[i].y = currentPos;
                else
                    centerWidgets[i].x = currentPos;
            }

            currentPos = (isVertical ? middleWidget.y : middleWidget.x) + middleSize;
            for (var i = middleIndex + 1; i < totalWidgets; i++) {
                currentPos += widgetSpacing;
                if (isVertical)
                    centerWidgets[i].y = currentPos;
                else
                    centerWidgets[i].x = currentPos;
                currentPos += isVertical ? centerWidgets[i].height : centerWidgets[i].width;
            }
            return;
        }

        if (totalWidgets === 1) {
            const widget = centerWidgets[0];
            const size = isVertical ? widget.height : widget.width;
            if (isVertical)
                widget.y = parentCenter - (size / 2);
            else
                widget.x = parentCenter - (size / 2);
            return;
        }

        if (!configuredLeftWidget || !configuredRightWidget) {
            if (totalWidgets % 2 === 1) {
                const middleIndex = Math.floor(totalWidgets / 2);
                const middleWidget = centerWidgets[middleIndex];

                if (!middleWidget)
                    return;

                const middleSize = isVertical ? middleWidget.height : middleWidget.width;

                if (isVertical)
                    middleWidget.y = parentCenter - (middleSize / 2);
                else
                    middleWidget.x = parentCenter - (middleSize / 2);

                let currentPos = isVertical ? middleWidget.y : middleWidget.x;
                for (var i = middleIndex - 1; i >= 0; i--) {
                    const size = isVertical ? centerWidgets[i].height : centerWidgets[i].width;
                    currentPos -= (widgetSpacing + size);
                    if (isVertical)
                        centerWidgets[i].y = currentPos;
                    else
                        centerWidgets[i].x = currentPos;
                }

                currentPos = (isVertical ? middleWidget.y : middleWidget.x) + middleSize;
                for (var i = middleIndex + 1; i < totalWidgets; i++) {
                    currentPos += widgetSpacing;
                    if (isVertical)
                        centerWidgets[i].y = currentPos;
                    else
                        centerWidgets[i].x = currentPos;
                    currentPos += isVertical ? centerWidgets[i].height : centerWidgets[i].width;
                }
            } else {
                const leftIndex = (totalWidgets / 2) - 1;
                const rightIndex = totalWidgets / 2;
                const fallbackLeft = centerWidgets[leftIndex];
                const fallbackRight = centerWidgets[rightIndex];

                if (!fallbackLeft || !fallbackRight)
                    return;

                const halfSpacing = widgetSpacing / 2;
                const leftSize = isVertical ? fallbackLeft.height : fallbackLeft.width;

                if (isVertical) {
                    fallbackLeft.y = parentCenter - halfSpacing - leftSize;
                    fallbackRight.y = parentCenter + halfSpacing;
                } else {
                    fallbackLeft.x = parentCenter - halfSpacing - leftSize;
                    fallbackRight.x = parentCenter + halfSpacing;
                }

                let currentPos = isVertical ? fallbackLeft.y : fallbackLeft.x;
                for (var i = leftIndex - 1; i >= 0; i--) {
                    const size = isVertical ? centerWidgets[i].height : centerWidgets[i].width;
                    currentPos -= (widgetSpacing + size);
                    if (isVertical)
                        centerWidgets[i].y = currentPos;
                    else
                        centerWidgets[i].x = currentPos;
                }

                currentPos = (isVertical ? fallbackRight.y + fallbackRight.height : fallbackRight.x + fallbackRight.width);
                for (var i = rightIndex + 1; i < totalWidgets; i++) {
                    currentPos += widgetSpacing;
                    if (isVertical)
                        centerWidgets[i].y = currentPos;
                    else
                        centerWidgets[i].x = currentPos;
                    currentPos += isVertical ? centerWidgets[i].height : centerWidgets[i].width;
                }
            }
            return;
        }

        const leftWidget = configuredLeftWidget;
        const rightWidget = configuredRightWidget;
        const leftIndex = centerWidgets.indexOf(leftWidget);
        const rightIndex = centerWidgets.indexOf(rightWidget);
        const halfSpacing = widgetSpacing / 2;
        const leftSize = isVertical ? leftWidget.height : leftWidget.width;

        if (isVertical) {
            leftWidget.y = parentCenter - halfSpacing - leftSize;
            rightWidget.y = parentCenter + halfSpacing;
        } else {
            leftWidget.x = parentCenter - halfSpacing - leftSize;
            rightWidget.x = parentCenter + halfSpacing;
        }

        let currentPos = isVertical ? leftWidget.y : leftWidget.x;
        for (var i = leftIndex - 1; i >= 0; i--) {
            const size = isVertical ? centerWidgets[i].height : centerWidgets[i].width;
            currentPos -= (widgetSpacing + size);
            if (isVertical)
                centerWidgets[i].y = currentPos;
            else
                centerWidgets[i].x = currentPos;
        }

        currentPos = (isVertical ? rightWidget.y + rightWidget.height : rightWidget.x + rightWidget.width);
        for (var i = rightIndex + 1; i < totalWidgets; i++) {
            currentPos += widgetSpacing;
            if (isVertical)
                centerWidgets[i].y = currentPos;
            else
                centerWidgets[i].x = currentPos;
            currentPos += isVertical ? centerWidgets[i].height : centerWidgets[i].width;
        }
    }

    height: parent.height
    width: parent.width
    anchors.centerIn: parent

    implicitWidth: isVertical ? widgetThickness : totalSize
    implicitHeight: isVertical ? totalSize : widgetThickness

    Timer {
        id: layoutTimer
        interval: 0
        repeat: false
        onTriggered: root.updateLayout()
    }

    Component.onCompleted: layoutTimer.restart()

    onWidthChanged: {
        if (width > 0)
            layoutTimer.restart();
    }

    onHeightChanged: {
        if (height > 0)
            layoutTimer.restart();
    }

    onVisibleChanged: {
        if (visible && (isVertical ? height : width) > 0)
            layoutTimer.restart();
    }

    Repeater {
        id: centerRepeater
        model: root.widgetsModel

        onCountChanged: layoutTimer.restart()

        Item {
            property var itemData: modelData
            readonly property real itemSpacing: root.widgetSpacing

            width: root.isVertical ? root.width : (widgetLoader.item ? widgetLoader.item.width : 0)
            height: widgetLoader.item ? widgetLoader.item.height : 0

            readonly property bool active: widgetLoader.active
            readonly property var item: widgetLoader.item
            readonly property bool itemVisible: widgetLoader.item?.visible ?? false

            onItemVisibleChanged: layoutTimer.restart()

            WidgetHost {
                id: widgetLoader

                anchors.verticalCenter: !root.isVertical ? parent.verticalCenter : undefined
                anchors.horizontalCenter: root.isVertical ? parent.horizontalCenter : undefined

                widgetId: itemData.widgetId
                widgetData: itemData
                spacerSize: itemData.size || 20
                components: root.components
                isInColumn: root.isVertical
                axis: root.axis
                section: "center"
                parentScreen: root.parentScreen
                widgetThickness: root.widgetThickness
                barThickness: root.barThickness
                barSpacing: root.barSpacing
                barConfig: root.barConfig
                blurBarWindow: root.blurBarWindow
                sectionAvailablePrimarySize: root.sectionAvailablePrimarySize
                isFirst: index === 0
                isLast: index === centerRepeater.count - 1
                sectionSpacing: parent.itemSpacing
                isLeftBarEdge: false
                isRightBarEdge: false
                isTopBarEdge: false
                isBottomBarEdge: false

                onContentItemReady: contentItem => {
                    contentItem.widthChanged.connect(() => layoutTimer.restart());
                    contentItem.heightChanged.connect(() => layoutTimer.restart());
                    layoutTimer.restart();
                }

                onActiveChanged: layoutTimer.restart()
            }
        }
    }

    Connections {
        target: SettingsData
        function onCenteringModeChanged() {
            layoutTimer.restart();
        }
    }
}
