/**************************************************************************
 **                                                                      **
 ** 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.Controls
import PhotoQt

GridView {

    id: gridview

    anchors.fill: parent

    model: 0

    property int baseSize: 50 + (PQCSettings.filedialogThumbnailSizeFollowsGlobalThumbnails ? PQCSettings.thumbnailsSize : PQCSettings.filedialogZoom)*5

    property bool ignoreMouseEvents: false
    interactive: !ignoreMouseEvents

    cellWidth: width / Math.floor(width / baseSize)
    cellHeight: baseSize

    ScrollBar.vertical: PQVerticalScrollBar { id: view_scroll }

    onContentYChanged: {
        // this check makes sure that value is not reset when a directory is reloaded due to a change
        if(contentY > 0)
            cacheContentY = contentY
    }

    PQScrollManager {
        flickable: gridview
        cursorShape: Qt.PointingHandCursor
    }

    // this pair stores the current scroll position
    // this way we can preserve that position when the content of the current directory changes
    property string cachePath: ""
    property real cacheContentY: 0.

    onCurrentIndexChanged: {
        if(PQGlobalItems.filedialogFileview === null) return
        if(PQGlobalItems.filedialogFileview.currentIndex !== currentIndex)
            PQGlobalItems.filedialogFileview.currentIndex = currentIndex
        if(!gridview.flicking)
            gridview.positionViewAtIndex(currentIndex, GridView.Contain)
    }

    onModelChanged: {
        // same folder reloaded
        if(PQCFileFolderModel.folderFileDialog === cachePath) {

            // restore position
            gridview.contentY = cacheContentY

        // new folder loaded
        } else {

            // reset position
            gridview.contentY = 0
            cachePath = PQCFileFolderModel.folderFileDialog
            cacheContentY = 0

        }

    }

    delegate:
    Rectangle {

        id: deleg

        required property int modelData

                                    // this check is necessary as some data might be available quicker than other. This avoid errant warnings.
        property string currentPath: modelData < PQCFileFolderModel.entriesFileDialog.length ? PQCFileFolderModel.entriesFileDialog[modelData] : ""
        property string currentFile: decodeURIComponent(PQCScriptsFilesPaths.getFilename(currentPath))
        property int numberFilesInsideFolder: 0
        property int padding: PQCSettings.filedialogElementPadding
        property bool isFolder: modelData < PQCFileFolderModel.countFoldersFileDialog
        property bool onNetwork: isFolder ? PQCScriptsFilesPaths.isOnNetwork(currentPath) : PQGlobalItems.filedialogFileview.currentFolderOnNetwork

        property bool isHovered: gridview.currentIndex===deleg.modelData
        property bool isSelected: PQCConstants.filedialogCurrentSelection.indexOf(deleg.modelData)>-1

        property bool isFileCut: PQGlobalItems.filedialogFileview.currentCuts.indexOf(deleg.modelData) > -1

        visible: currentPath!=""

        width: gridview.cellWidth
        height: gridview.cellHeight

        color: palette.base
        border.width: 1
        border.color: PQCLook.baseBorder

        Item {
            id: dragHandler

            x: PQCSettings.filedialogElementPadding
            y: PQCSettings.filedialogElementPadding
            width: deleg.width - 2*PQCSettings.filedialogElementPadding
            height: deleg.height - 2*PQCSettings.filedialogElementPadding

        }

        // the file type icon
        PQFileIcon {

            id: fileicon

            gridlike: true

            isFileCut: deleg.isFileCut
            onNetwork: deleg.onNetwork
            isFolder: deleg.isFolder
            currentPath: deleg.currentPath

            x: PQCSettings.filedialogElementPadding
            y: PQCSettings.filedialogElementPadding
            width: deleg.width - 2*PQCSettings.filedialogElementPadding
            height: deleg.height - 2*PQCSettings.filedialogElementPadding

        }

        // the file thumbnail
        PQFileThumb {

            id: filethumb

            isFileCut: deleg.isFileCut
            isFolder: deleg.isFolder
            onNetwork: deleg.onNetwork
            currentPath: deleg.currentPath
            myIndex: deleg.modelData

            x: PQCSettings.filedialogElementPadding
            y: PQCSettings.filedialogElementPadding
            width: deleg.width - 2*PQCSettings.filedialogElementPadding
            height: deleg.height - 2*PQCSettings.filedialogElementPadding

            function onHideFileIcon() {
                fileicon.source = ""
            }

            function onShowFileIcon() {
                fileicon.source = fileicon.sourceString
            }

        }

        // the folder thumbnails
        PQFolderThumb {

            id: folderthumb

            isFileCut: deleg.isFileCut
            myIndex: deleg.modelData
            isFolder: deleg.isFolder
            numberFilesInsideFolder: deleg.numberFilesInsideFolder

            x: PQCSettings.filedialogElementPadding
            y: PQCSettings.filedialogElementPadding
            width: deleg.width - 2*PQCSettings.filedialogElementPadding
            height: deleg.height - 2*PQCSettings.filedialogElementPadding

            function onHideFileIcon() {
                fileicon.source = ""
            }

        }

        /************************************************************/
        // FILE NAME AND SIZE

        // the filename - icon view
        Loader {

            active: PQCSettings.filedialogLabelsShowGrid||deleg.isFolder

            sourceComponent:
            Item {
                id: filename_label
                width: deleg.width
                height: deleg.height/4 + (deleg.isSelected||deleg.isHovered ? 10 : 0)
                Behavior on height { enabled: !PQCSettings.generalDisableAllAnimations; NumberAnimation { duration: 200 } }
                y: deleg.height-height
                Rectangle {
                    anchors.fill: parent
                    color: palette.base
                    Behavior on color { enabled: !PQCSettings.generalDisableAllAnimations; ColorAnimation { duration: 200 } }
                    border.width: 1
                    border.color: palette.button
                }

                PQText {
                    id: filename
                    anchors.fill: parent
                    anchors.margins: 5
                    verticalAlignment: Text.AlignVCenter
                    horizontalAlignment: Text.AlignHCenter
                    maximumLineCount: 2
                    elide: Text.ElideMiddle
                    text: deleg.currentFile
                    color: palette.text
                    Behavior on color { enabled: !PQCSettings.generalDisableAllAnimations; ColorAnimation { duration: 200 } }
                }

                Image {
                    x: (parent.width-width-5)
                    y: (parent.height-height-5)
                    source: "image://svg/:/light/folder.svg"
                    height: 16
                    mipmap: true
                    width: height
                    opacity: 0.3
                    visible: deleg.isFolder && folderthumb.curnum!==0
                }
            }

        }

        // this is a dummy item to be able to reuse some logic from other views
        Item {
            id: fileinfo
            property string text: ""
        }

        /************************************************************/
        // HIGHLIGHT/SELECT

        PQHighlightMarker {
            anchors.margins: 0
            opacity: !deleg.isSelected ? 0.5 : 1
            visible: deleg.isHovered || deleg.isSelected
        }

        /************************************************************/
        // meta information

        // how many files inside folder
        Rectangle {
            id: numberOfFilesInsideFolder_cont
            x: (deleg.width-width)-5
            y: 5
            width: numberOfFilesInsideFolder.width + 20
            height: 30
            radius: 5
            color: palette.text
            opacity: 0.8
            visible: numberOfFilesInsideFolder.text !== "" && numberOfFilesInsideFolder.text !== "0"

            PQText {
                id: numberOfFilesInsideFolder
                x: 10
                y: (parent.height-height)/2-2
                font.weight: PQCLook.fontWeightBold
                color: palette.base
                elide: Text.ElideMiddle
                text: deleg.numberFilesInsideFolder
            }
        }

        // which # thumbnail inside folder
        Rectangle {
            id: numberThumbInsideFolderCont
            x: (deleg.width-width)/2
            y: 10
            width: numberThumbInsideFolder.width + 10
            height: 20
            radius: 3
            color: palette.text
            opacity: 0.6
            visible: folderthumb.curnum>0 && folderthumb.visible

            PQTextS {
                id: numberThumbInsideFolder
                x: 5
                y: (parent.height-height)/2-2
                font.weight: PQCLook.fontWeightBold
                visible: folderthumb.curnum>0
                color: palette.base
                elide: Text.ElideMiddle
                text: "#"+folderthumb.curnum
            }
        }

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

        // mouse area handling general mouse events
        PQMouseArea {

            id: gridmousearea

            anchors.fill: parent

            hoverEnabled: true
            cursorShape: Qt.PointingHandCursor

            Connections {
                target: PQCConstants
                function onWhichContextMenusOpenChanged() {
                    if(PQCConstants.isContextmenuOpen("fileviewentry"))
                        gridmousearea.closeTooltip()
                }
            }

            acceptedButtons: Qt.LeftButton|Qt.RightButton|Qt.BackButton|Qt.ForwardButton

            drag.target: PQCSettings.filedialogDragDropFileviewGrid ? dragHandler : undefined

            drag.onActiveChanged: {
                if(drag.active) {
                    // store which index is being dragged and that the entry comes from the userplaces (reordering only)
                    PQGlobalItems.filedialogPlaces.dragItemIndex = deleg.modelData
                    PQGlobalItems.filedialogPlaces.dragReordering = false
                    PQGlobalItems.filedialogPlaces.dragItemId = deleg.currentPath
                }
                deleg.Drag.drop();
                if(!drag.active) {
                    // reset variables used for drag/drop
                    PQGlobalItems.filedialogPlaces.dragItemIndex = -1
                    PQGlobalItems.filedialogPlaces.dragItemId = ""
                }
            }

            onPressed: {

                if(!PQCConstants.isContextmenuOpen("fileviewentry"))
                    PQGlobalItems.filedialogFileview.currentIndex = deleg.modelData

                // we only need this when a potential drag might occur
                // otherwise no need to load this drag thumbnail
                deleg.dragImageSource = "image://dragthumb/" + deleg.currentPath + ":://::" + (PQGlobalItems.filedialogFileview.currentFileSelected ? PQCConstants.filedialogCurrentSelection.length : 1)

            }

            onEntered: {

                tooltip = ""
                tooltip = PQGlobalItems.filedialogFileview.handleEntriesMouseEnter(deleg.modelData, deleg.currentPath, filethumb.status, fileinfo.text,
                                                                                   deleg.isFolder, deleg.numberFilesInsideFolder, folderthumb.curnum)

            }

            onExited: {
                if(!selectmouse.containsMouse)
                    PQGlobalItems.filedialogFileview.handleEntriesMouseExit(deleg.modelData)
            }

            onClicked: (mouse) => {

                PQGlobalItems.filedialogFileview.handleEntriesMouseClick(deleg.modelData, deleg.currentPath, deleg.isFolder,
                                                 mouse.modifiers, mouse.button)

            }

        }

        /************************************************************/
        // + ICON TO SELECT/ - ICON TO DESELECT
        // has to be on top of main mouse area

        Rectangle {
            id: selectedornot
            x: 5
            y: 5
            width: 30
            height: 30
            radius: 5

            color: "#bbbbbb"
            opacity: (selectmouse.containsMouse||PQCConstants.filedialogCurrentSelection.indexOf(deleg.modelData)!==-1)
                            ? 0.8
                            : (PQGlobalItems.filedialogFileview.currentIndex===deleg.modelData
                                    ? 0.8 : 0)
            Behavior on opacity { enabled: !PQCSettings.generalDisableAllAnimations; NumberAnimation { duration: 200 } }

            Image {
                anchors.fill: parent
                source: (PQCConstants.filedialogCurrentSelection.indexOf(deleg.modelData)!==-1 ? ("image://svg/:/" + PQCLook.iconShade + "/deselectfile.svg") : ("image://svg/:/" + PQCLook.iconShade + "/selectfile.svg"))
                mipmap: true
                opacity: selectmouse.containsMouse ? 0.8 : 0.4
                Behavior on opacity { enabled: !PQCSettings.generalDisableAllAnimations; NumberAnimation { duration: 200 } }
                MouseArea {
                    id: selectmouse
                    anchors.fill: parent
                    hoverEnabled: true
                    cursorShape: Qt.PointingHandCursor
                    onClicked: {
                        if(!PQGlobalItems.filedialogFileview.currentFileSelected) {
                            PQGlobalItems.filedialogFileview.shiftClickIndexStart = deleg.modelData
                            PQCConstants.filedialogCurrentSelection.push(deleg.modelData)
                            PQCConstants.filedialogCurrentSelectionChanged()
                        } else {
                            PQGlobalItems.filedialogFileview.shiftClickIndexStart = -1
                            PQCConstants.filedialogCurrentSelection = PQCConstants.filedialogCurrentSelection.filter(item => item!==deleg.modelData)
                        }
                    }
                    onEntered: {
                        PQGlobalItems.filedialogFileview.currentIndex = deleg.modelData
                    }
                }
            }

        }

        Drag.active: gridmousearea.drag.active
        Drag.mimeData: {
            if(!PQGlobalItems.filedialogFileview.currentFileSelected) {
                return ({"text/uri-list": encodeURI("file:"+deleg.currentPath)})
            } else {
                var uris = []
                for(var i in PQCConstants.filedialogCurrentSelection)
                    uris.push(encodeURI("file:" + PQCFileFolderModel.entriesFileDialog[PQCConstants.filedialogCurrentSelection[i]]))
                return ({"text/uri-list": uris})
            }
        }
        Drag.dragType: Drag.Automatic

        // this is set in the mousearea's onPressed signal
        // this avoid loading all drag thumbnails at the start
        property string dragImageSource: ""
        Drag.imageSource: dragImageSource

        Component.onCompleted: {
            PQCScriptsFileDialog.getNumberOfFilesInFolder(deleg.currentPath)
        }

        Connections {
            target: PQCScriptsFileDialog
            function onFiguredOutNumberOfFilesInFolder(path : string, num : int) {
                if(deleg.currentPath !== path) return
                if(num > 0) {
                    deleg.numberFilesInsideFolder = num
                    fileinfo.text = (num===1 ? qsTranslate("filedialog", "%1 image").arg(num) : qsTranslate("filedialog", "%1 images").arg(num))
                }
            }
        }

    }

    function goDownARow() {

        if(PQGlobalItems.filedialogFileview.currentIndex === -1)
            PQGlobalItems.filedialogFileview.currentIndex = 0
        else
            PQGlobalItems.filedialogFileview.currentIndex = Math.min(PQCFileFolderModel.countAllFileDialog-1, PQGlobalItems.filedialogFileview.currentIndex + Math.floor(gridview.width/gridview.cellWidth))

    }

    function goDownSomeRows() {

        if(PQGlobalItems.filedialogFileview.currentIndex === -1)
            PQGlobalItems.filedialogFileview.currentIndex = Math.min(PQCFileFolderModel.countAllFileDialog-1, 4*Math.floor(gridview.width/gridview.cellWidth))
        else
            PQGlobalItems.filedialogFileview.currentIndex = Math.min(PQCFileFolderModel.countAllFileDialog-1, PQGlobalItems.filedialogFileview.currentIndex + 5*Math.floor(gridview.width/gridview.cellWidth))

    }

    function goUpARow() {

        if(PQGlobalItems.filedialogFileview.currentIndex === -1)
            PQGlobalItems.filedialogFileview.currentIndex = PQCFileFolderModel.countAllFileDialog-1
        else
            PQGlobalItems.filedialogFileview.currentIndex = Math.max(0, PQGlobalItems.filedialogFileview.currentIndex - Math.floor(gridview.width/gridview.cellWidth))

    }

    function goUpSomeRows() {

        if(PQGlobalItems.filedialogFileview.currentIndex === -1)
            PQGlobalItems.filedialogFileview.currentIndex = Math.max(0, PQCFileFolderModel.countAllFileDialog-1 - 4*Math.floor(gridview.width/gridview.cellWidth))
        else
            PQGlobalItems.filedialogFileview.currentIndex = Math.max(0, PQGlobalItems.filedialogFileview.currentIndex - 5*Math.floor(gridview.width/gridview.cellWidth))

    }

}
