/*
    SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
    SPDX-FileCopyrightText: 2014 Sebastian Kügler <sebas@kde.org>
    SPDX-FileCopyrightText: 2014 Kai Uwe Broulik <kde@privat.broulik.de>

    SPDX-License-Identifier: GPL-2.0-or-later
*/

import QtQuick
import QtQuick.Controls as QQC2
import org.kde.plasma.wallpapers.image as Wallpaper
import org.kde.kirigami as Kirigami

QQC2.StackView {
    id: view

    required property int fillMode
    required property string configColor
    required property bool blur
    property alias source: mediaProxy.source
    required property size sourceSize
    required property /*WallpaperItem*/ QtObject wallpaperInterface // weaker type to support mock object in autotests

    readonly property alias mediaProxy: mediaProxy
    readonly property url modelImage: mediaProxy.modelImage
    property bool forceImageAnimation: false

    /**
     * Stores pending image here to avoid the default image overriding the true image.
     *
     * @see BUG 456189
     */
    property Item pendingImage

    property bool doesSkipAnimation: true

    property Component staticImageComponent
    property Component animatedImageComponent
    property Component dayNightComponent

    onFillModeChanged: Qt.callLater(loadImage);
    onModelImageChanged: Qt.callLater(loadImage);
    onConfigColorChanged: Qt.callLater(loadImage);
    onBlurChanged: Qt.callLater(loadImage);

    function createBackgroundComponent() {
        switch (mediaProxy.backgroundType) {
        case Wallpaper.BackgroundType.Image:
        case Wallpaper.BackgroundType.VectorImage: {
            if (!staticImageComponent) {
                staticImageComponent = Qt.createComponent("mediacomponent/StaticImageComponent.qml");
            }
            return staticImageComponent;
        }
        case Wallpaper.BackgroundType.AnimatedImage: {
            if (!animatedImageComponent) {
                animatedImageComponent = Qt.createComponent("mediacomponent/AnimatedImageComponent.qml");
            }
            return animatedImageComponent;
        }
        case Wallpaper.BackgroundType.DayNight: {
            if (!dayNightComponent) {
                dayNightComponent = Qt.createComponent("mediacomponent/DayNightComponent.qml");
            }
            return dayNightComponent;
        }
        }
    }

    function loadImageImmediately() {
        loadImage(true);
    }

    function loadImage(skipAnimation) {
        if (pendingImage) {
            pendingImage.statusChanged.disconnect(replaceWhenLoaded);
            pendingImage.destroy();
            pendingImage = null;
        }

        if (mediaProxy.providerType == Wallpaper.Provider.Unknown) {
            console.error("The backend got an unknown wallpaper provider type. The wallpaper will now fall back to the default. Please check your wallpaper configuration!");
            mediaProxy.useSingleImageDefaults();
            return;
        }

        doesSkipAnimation = view.currentItem == undefined || view.currentItem.sourceSize !== view.sourceSize || !!skipAnimation;
        const baseImage = createBackgroundComponent();
        const properties = {
            // Use mediaProxy instead of view because colorSchemeChanged needs immediately update the wallpaper
            "source": mediaProxy.modelImage,
            "fillMode": view.fillMode,
            "sourceSize": view.sourceSize,
            "color": view.configColor,
            "blur": view.blur,
            "parent": view,
            "implicitWidth": view.width,
            "implicitHeight": view.height,
            "visible": false,
        };
        // Only pass forceImageAnimation for AnimatedImageComponent
        if (mediaProxy.backgroundType === Wallpaper.BackgroundType.AnimatedImage) {
            properties.forceImageAnimation = view.forceImageAnimation;
        }
        pendingImage = baseImage.createObject(view, properties);

        if (!pendingImage) {
            console.warn(baseImage.errorString());
            return;
        }

        pendingImage.statusChanged.connect(replaceWhenLoaded);
        replaceWhenLoaded();
    }

    function replaceWhenLoaded() {
        if (pendingImage.status === Image.Loading) {
            return;
        }

        pendingImage.statusChanged.disconnect(replaceWhenLoaded);
        // BUG 454908: Update accent color
        pendingImage.QQC2.StackView.onActivated.connect(() => {
            if (Qt.colorEqual(mediaProxy.customColor, "transparent") && Qt.colorEqual(wallpaperInterface.accentColor, "transparent")) {
                wallpaperInterface.accentColorChanged();
            } else {
                wallpaperInterface.accentColor = mediaProxy.customColor;
            }
        });

        // onRemoved only fires when all transitions end. If a user switches wallpaper quickly this adds up
        // Given it's such a heavy item, try to cleanup as early as possible
        pendingImage.QQC2.StackView.onDeactivated.connect(pendingImage.destroy);
        pendingImage.QQC2.StackView.onRemoved.connect(pendingImage.destroy);
        view.replace(pendingImage, {}, QQC2.StackView.Transition);

        wallpaperInterface.loading = false;

        if (pendingImage.status !== Image.Ready) {
            mediaProxy.useSingleImageDefaults();
        }

        pendingImage = null;
    }

    replaceEnter: Transition {
        NumberAnimation {
            id: replaceEnterOpacityAnimator
            property: "opacity"
            from: 0
            to: 1
            // The value is to keep compatible with the old feeling defined by "TransitionAnimationDuration" (default: 1000)
            duration: Math.round(Kirigami.Units.veryLongDuration * 2.5)
        }
        enabled: !view.doesSkipAnimation
    }
    // Keep the old image around till the new one is fully faded in
    // If we fade both at the same time you can see the background behind glimpse through
    replaceExit: Transition{
        PauseAnimation {
            // 500: The exit transition starts first and can be completed earlier than the enter transition
            duration: replaceEnterOpacityAnimator.duration + 500
        }
    }

    Wallpaper.MediaProxy {
        id: mediaProxy

        targetSize: view.sourceSize

        onActualSizeChanged: Qt.callLater(view.loadImageImmediately);
        onColorSchemeChanged: view.loadImageImmediately();
        onSourceFileUpdated: view.loadImageImmediately()
    }
}
