/**************************************************************************
 **                                                                      **
 ** Copyright (C) 2011-2026 Lukas Spies                                  **
 ** Contact: https://photoqt.org                                         **
 **                                                                      **
 ** This file is part of PhotoQt.                                        **
 **                                                                      **
 ** PhotoQt is free software: you can redistribute it and/or modify      **
 ** it under the terms of the GNU General Public License as published by **
 ** the Free Software Foundation, either version 2 of the License, or    **
 ** (at your option) any later version.                                  **
 **                                                                      **
 ** PhotoQt is distributed in the hope that it will be useful,           **
 ** but WITHOUT ANY WARRANTY; without even the implied warranty of       **
 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        **
 ** GNU General Public License for more details.                         **
 **                                                                      **
 ** You should have received a copy of the GNU General Public License    **
 ** along with PhotoQt. If not, see <http://www.gnu.org/licenses/>.      **
 **                                                                      **
 **************************************************************************/
pragma ComponentBehavior: Bound

import QtQuick
import QtQuick.Window
import QtQuick.Controls
import PhotoQt

ApplicationWindow {

    id: toplevel


    flags: isIntegrated ? Qt.Window :
                PQCSettings.interfaceWindowDecoration ?
               (PQCSettings.interfaceKeepWindowOnTop ? (Qt.Window|Qt.WindowStaysOnTopHint|Qt.WindowTitleHint|Qt.WindowMinMaxButtonsHint|Qt.WindowCloseButtonHint) : Qt.Window) :
               (PQCSettings.interfaceKeepWindowOnTop ? (Qt.FramelessWindowHint|Qt.WindowStaysOnTopHint|Qt.Window|Qt.WindowMinMaxButtonsHint|Qt.WindowCloseButtonHint) : (Qt.FramelessWindowHint|Qt.Window|Qt.WindowMinMaxButtonsHint))

    color: isModern ? "transparent" : palette.base

    property string titleOverride: ""
    title: titleOverride!="" ?
               (titleOverride + " | PhotoQt") :
               ((PQCFileFolderModel.currentFile==="" ? "" : (PQCScriptsFilesPaths.getFilename(PQCFileFolderModel.currentFile) + " | "))+ "PhotoQt")

    minimumWidth: 300
    minimumHeight: 200

    // if last geometry has been remembered that one is set in the show() function below
    width: 800
    height: 600

    property bool isModern: PQCSettings.generalInterfaceVariant==="modern"
    property bool isIntegrated: !isModern

    // this signals whether the window is currently being resized or not
    onWidthChanged: {
        storeWindowGeometry.restart()
        PQCConstants.availableWidth = width- ((isIntegrated && PQCSettings.metadataSideBar) ? PQCSettings.metadataSideBarWidth : 0)
        PQCConstants.mainWindowBeingResized = true
        resetResizing.restart()
    }
    onHeightChanged: {
        storeWindowGeometry.restart()
        PQCConstants.availableHeight = height-(isIntegrated ? ((footer.visible?footer.height:0)+(menuBar.visible?menuBar.height:0)) : 0)
        PQCConstants.mainWindowBeingResized = true
        resetResizing.restart()
    }
    onXChanged: {
        storeWindowGeometry.restart()
    }
    onYChanged: {
        storeWindowGeometry.restart()
    }

    /**************************************/
        // INTEGRATED INTERFACE ONLY
        Connections {
            target: PQCSettings
            enabled: toplevel.isIntegrated
            function onMetadataSideBarWidthChanged() {
                PQCConstants.availableWidth = toplevel.width - (PQCSettings.metadataSideBar ? PQCSettings.metadataSideBarWidth : 0)
            }
            function onMetadataSideBarChanged() {
                PQCConstants.availableWidth = toplevel.width - (PQCSettings.metadataSideBar ? PQCSettings.metadataSideBarWidth : 0)
            }
            function onInterfaceStatusInfoShowChanged() {
                PQCConstants.availableHeight = toplevel.height-(toplevel.isIntegrated ? ((footer.visible?footer.height:0)+(menuBar.visible?menuBar.height:0)) : 0)
            }
        }

    /**************************************/

    Timer {
        id: resetResizing
        interval: 500
        onTriggered: {
            PQCConstants.mainWindowBeingResized = false
        }
    }

    // we store this with a delay to make sure the visibility properyt is properly updated
    Timer {
        id: storeWindowGeometry
        interval: 200
        onTriggered: {

            if(PQCConstants.photoQtShuttingDown)
                return

            if(toplevel.visibility === Window.Windowed) {
                PQCWindowGeometry.mainWindowGeometry = Qt.rect(toplevel.x, toplevel.y, toplevel.width, toplevel.height)
                PQCWindowGeometry.mainWindowMaximized = false
            } else if(toplevel.visibility === Window.Maximized)
                PQCWindowGeometry.mainWindowMaximized = true

        }

    }

    property bool isFullscreen: toplevel.visibility==Window.FullScreen

    onVisibilityChanged: (visibility) => {

        storeWindowGeometry.restart()

        // we keep track of whether a window is maximized or windowed
        // when restoring the window we then can restore it to the state it was in before
        if(visibility === Window.Maximized)
            PQCConstants.windowMaxAndNotWindowed = true
        else if(visibility === Window.Windowed)
            PQCConstants.windowMaxAndNotWindowed = false

        PQCConstants.windowFullScreen = (visibility === Window.FullScreen)

    }

    /**************************************/
        // INTEGRATED INTERFACE ONLY
        Loader {
            anchors.fill: parent
            active: toplevel.isIntegrated
            // divider between menubar and content
            Rectangle {
                width: parent.width
                height: 1
                color: palette.disabled.text
                opacity: 0.5
            }
            // divider between footer and content
            Rectangle {
                y: (parent.height-height)
                width: parent.width
                height: 1
                color: palette.disabled.text
                opacity: 0.5
            }
        }
        menuBar: PQMenuBarIntegrated { visible: toplevel.isIntegrated&&!toplevel.isFullscreen }
        footer: PQFooterIntegrated { visible: toplevel.isIntegrated&&PQCSettings.interfaceStatusInfoShow&&!toplevel.isFullscreen }
    /**************************************/

    Item {
        id: fullscreenitem
        anchors.fill: parent
        Component.onCompleted:
            PQGlobalItems.toplevelItem = fullscreenitem
    }

    Connections {
        target: PQCNotify
        function onResetActiveFocus() {
            fullscreenitem.forceActiveFocus()
        }
    }

    /**************************************/

        // MODERN INTERFACE ONLY
        PQLoaderMainWindowBackgroundModern {}
    PQLoaderBackgroundMessage {}

    PQLoaderImage { id: imageloader }

        // INTEGRATED INTERFACE ONLY
        PQLoaderSideBarIntegrated { whichside: "left" }
        PQLoaderSideBarIntegrated { whichside: "right"; x: toplevel.width-width }

    PQLoaderShortcuts { id: shortcuts }

    // This is a Loader that loads the rest of the application in the background after set up
    PQMasterItem {
        id: masteritemattop
        z: 2
    }

    PQLoaderLoader {
        id: masterloader
        onShowExtension: (ele) => {
            masteritemattop.showExtension(ele)
        }
    }

    /****************************************************/
    /****************************************************/

    // this needs to be out here to be loaded faster if needed
    PQLoaderFileDialog {}

    /****************************************************/
    /****************************************************/

    Loader {
        active: PQCScriptsConfig.isBetaVersion() && toplevel.isModern
        sourceComponent:
        PQText {
            x: fullscreenitem.width-width-5
            y: fullscreenitem.height-height-5
            z: 9999
            parent: fullscreenitem.parent
            font.weight: PQCLook.fontWeightBold
            opacity: 0.5
            text: "This is a beta release and is intended for testing only."
        }
    }

    /****************************************************/
    /****************************************************/

    Timer {
        id: setVersion
        interval: 1
        onTriggered:
            PQCSettings.generalVersion = PQCScriptsConfig.getVersion()
    }

    Timer {
        id: loadAppInBackgroundTimer
        interval: 100
        onTriggered:
            masteritemattop.active = true
    }

    /****************************************************/

    // this is called only when triggered from status info
    // if this is not done with a short delay then the state is not applied properly
    Timer {
        id: setStateTimer
        interval: 100
        property int newstate
        onTriggered: {
            toplevel.visibility = newstate
        }
    }

    /****************************************************/

    function setXYWidthHeight(geo : rect) {
        toplevel.x = geo.x
        toplevel.y = geo.y
        toplevel.width = geo.width
        toplevel.height = geo.height
    }

    Component.onCompleted: {

        PQGlobalItems.rootWindow = toplevel

        PQCScriptsLocalization.updateTranslation(PQCSettings.interfaceLanguage)

        const fadeInWindow = (PQCScriptsConfig.amIOnWindows() && !PQCConstants.startupStartInTray && PQCSettings.generalInterfaceVariant==="modern")

        if(fadeInWindow)
            toplevel.opacity = 0

        // show window according to settings
        // the integrated interface is always shown in window mode
        if(PQCSettings.interfaceWindowMode || isIntegrated) {
            if(PQCSettings.interfaceSaveWindowGeometry) {
                setXYWidthHeight(PQCWindowGeometry.mainWindowGeometry)
                if(PQCConstants.startupStartInTray) {
                    PQCSettings.interfaceTrayIcon = 1
                    toplevel.hide()
                } else {
                    if(PQCWindowGeometry.mainWindowMaximized)
                        showMaximized()
                    else
                        showNormal()
                }
            } else {
                if(PQCConstants.startupStartInTray) {
                    PQCSettings.interfaceTrayIcon = 1
                    toplevel.hide()
                } else
                    showMaximized()
            }
        } else {
            if(PQCConstants.startupStartInTray) {
                PQCSettings.interfaceTrayIcon = 1
                toplevel.hide()
            } else
                showFullScreen()
        }

        // Make sure to set the current screen name on startup
        if(toplevel.screen !== undefined)
            PQCConstants.currentScreenModelName = toplevel.screen.name

        if(PQCConstants.startupFilePath !== "") {

            // in the case of a FOLDER passed on we actually need to load the files first to get the first one:
            if(PQCConstants.startupFileIsFolder)
                PQCFileFolderModel.fileInFolderMainView = PQCConstants.startupFilePath

        } else if(PQCSettings.interfaceRememberLastImage) {

            PQCConstants.startupFilePath = PQCScriptsConfig.getLastLoadedImage()
            PQCConstants.startupFileIsFolder = PQCScriptsFilesPaths.isFolder(PQCConstants.startupFilePath)

        }

        // this comes after the above to make sure we load a potentially passed-on image
        imageloader.active = true

        PQCNotify.reprocessStartupMessage();

        if(fadeInWindow)
            showOpacity.restart()

        if(PQCConstants.startupFilePath === "")
            loadAppInBackgroundTimer.triggered()
        else
            loadAppInBackgroundTimer.start()

        setVersion.start()

    }

    Connections {

        target: PQCSettings

        function onInterfaceWindowModeChanged() {
            toplevel.visibility = (PQCSettings.interfaceWindowMode ? (PQCConstants.windowMaxAndNotWindowed ? Window.Maximized : Window.Windowed) : Window.FullScreen)
        }

    }

    Connections {

        target: PQCConstants

        function onStartupFilePathChanged() : void {
            console.log("")
            PQCFileFolderModel.fileInFolderMainView = PQCConstants.startupFilePath
            PQCNotify.loaderPassOn("forceCloseEverything", [])
            if(PQCFileFolderModel.folderFileDialog !== "") {
                if(PQCScriptsFilesPaths.isFolder(PQCConstants.startupFilePath))
                    PQCFileFolderModel.folderFileDialog = PQCConstants.startupFilePath
                else
                    PQCFileFolderModel.folderFileDialog = PQCScriptsFilesPaths.getDir(PQCConstants.startupFilePath)
            }
            toplevel.visible = true
            if(toplevel.visibility === Window.Minimized)
                toplevel.visibility = (PQCConstants.windowMaxAndNotWindowed ? Window.Maximized : Window.Windowed)
            toplevel.raise()
            toplevel.requestActivate()
        }

    }

    Connections {

        target: PQCNotify

        function onCmdOpen() : void {
            console.log("")
            PQCNotify.loaderShow("FileDialog")
        }

        function onCmdShow() : void {

            console.log("")

            if(toplevel.visible) {
                toplevel.raise()
                toplevel.requestActivate()
                return
            }

            toplevel.visible = true
            if(toplevel.visibility === Window.Minimized)
                toplevel.visibility = (PQCConstants.windowMaxAndNotWindowed ? Window.Maximized : Window.Windowed)
            toplevel.raise()
            toplevel.requestActivate()

        }

        function onCmdHide() : void {
            console.log("")
            PQCSettings.interfaceTrayIcon = 1
            toplevel.close()
        }

        function onCmdQuit() : void {
            console.log("")
            toplevel.quitPhotoQt()
        }

        function onCmdToggle() : void {

            console.log("")

            if(toplevel.visible) {
                PQCSettings.interfaceTrayIcon = 1
                toplevel.close()
            } else {
                toplevel.visible = true
                if(toplevel.visibility === Window.Minimized)
                    toplevel.visibility = (PQCConstants.windowMaxAndNotWindowed ? Window.Maximized : Window.Windowed)
                toplevel.raise()
                toplevel.requestActivate()
            }

        }

        function onCmdTray(enabled : bool) : void {

            console.log("args: enabled =", enabled)

            if(enabled && PQCSettings.interfaceTrayIcon === 0)
                PQCSettings.interfaceTrayIcon = 2
            else if(!enabled) {
                PQCSettings.interfaceTrayIcon = 0
                if(!toplevel.visible) {
                    toplevel.visible = true
                    if(toplevel.visibility === Window.Minimized)
                        toplevel.visibility = (PQCConstants.windowMaxAndNotWindowed ? Window.Maximized : Window.Windowed)
                    toplevel.raise()
                    toplevel.requestActivate()
                }
            }

        }

        function onSetWindowState(state : int) {
            setStateTimer.newstate = state
            setStateTimer.restart()
        }

        function onWindowRaiseAndFocus() {
            toplevel.raise()
            toplevel.requestActivate()
        }

        function onWindowClose() {
            toplevel.close()
        }

        function onWindowTitleOverride(title : string) {
            toplevel.titleOverride = title
        }

        function onWindowStartSystemMove() {
            toplevel.startSystemMove()
        }

        function onWindowStartSystemResize(edge : int) {
            toplevel.startSystemResize(edge)
        }

        function onPhotoQtQuit() {
            toplevel.quitPhotoQt()
        }

    }

    // this reacts to changes to which screen the window is displayed on
    // this is necessary in order to handle different device/pixel ratios for
    // different screens
    onScreenChanged: {
        if(toplevel.screen !== undefined) {
            PQCConstants.currentScreenModelName = toplevel.screen.name
        }
    }

    function handleBeforeClosing() {

        PQCFileFolderModel.advancedSortMainViewCANCEL()

        if(PQCFileFolderModel.currentIndex > -1 && PQCSettings.interfaceRememberLastImage)
            PQCScriptsConfig.setLastLoadedImage(PQCFileFolderModel.currentFile)
        else
            PQCScriptsConfig.deleteLastLoadedImage()

        PQCScriptsFilesPaths.cleanupTemporaryFiles()

        PQCScriptsOther.deleteScreenshots()

    }

    onClosing: (close) => {

        PQCConstants.photoQtShuttingDown = true
        PQCNotify.photoqtShuttingDown()

        // We stop a running slideshow to make sure all settings are restored to their normal state
        if(PQCConstants.slideshowRunning)
            PQCNotify.slideshowHideHandler()

        if(PQCSettings.interfaceTrayIcon === 1) {
            close.accepted = false
            toplevel.visibility = Window.Hidden
            if(PQCSettings.interfaceTrayIconHideReset)
                PQCNotify.resetSessionData()
            PQCConstants.photoQtShuttingDown = false
        } else {
            close.accepted = true
            quitPhotoQt()
        }
    }

    function quitPhotoQt() {
        handleBeforeClosing()
        Qt.quit()
    }

    /*************************************************/

    // on windows there is a white flash when the window is created
    // thus we set up the window with opacity set to 0
    // and this animation fades the window without white flash
    PropertyAnimation {
        id: showOpacity
        target: toplevel
        property: "opacity"
        from: 0
        to: 1
        duration: 100
    }

}
