/*****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQuick.Dialogs module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
**     of its contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
*****************************************************************************/

import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Private 1.0 as ControlsPrivate
import QtQuick.Dialogs 1.1
import QtQuick.Dialogs.Private 1.1
import QtQuick.Layouts 1.1
import QtQuick.Window 2.1
import Qt.labs.folderlistmodel 2.1
import Qt.labs.settings 1.0

AbstractFileDialog {
    id: root
    onVisibleChanged: {
        if (visible) {
            view.needsWidthAdjustment = true
            view.selection.clear()
        }
    }

    Component.onCompleted: {
        view.model.nameFilters = root.selectedNameFilterExtensions
        filterField.currentIndex = root.selectedNameFilterIndex
        root.favoriteFolders = settings.favoriteFolders
        root.folder = view.model.folder
    }

    Component.onDestruction: {
        settings.favoriteFolders = root.favoriteFolders
    }

    property Settings settings: Settings {
        category: "QQControlsFileDialog"
        property alias width: root.width
        property alias height: root.height
        property alias sidebarWidth: sidebar.width
        property alias sidebarSplit: shortcuts.height
        property variant favoriteFolders: []
    }

    property bool showFocusHighlight: false
    property SystemPalette palette: SystemPalette { }
    property var favoriteFolders: []

    function dirDown(path) {
        view.selection.clear()
        root.folder = "file://" + path
    }
    function dirUp() {
        view.selection.clear()
        if (view.model.parentFolder != "")
            root.folder = view.model.parentFolder
    }
    function acceptSelection() {
        // transfer the view's selections to QQuickFileDialog
        clearSelection()
        if (selectFolder && view.selection.count === 0)
            addSelection(folder)
        else {
            view.selection.forEach(function(idx) {
                if (view.model.isFolder(idx)) {
                    if (selectFolder)
                        addSelection(view.model.get(idx, "fileURL"))
                } else {
                    if (!selectFolder)
                        addSelection(view.model.get(idx, "fileURL"))
                }
            })
        }
        accept()
    }

    property Action dirUpAction: Action {
        text: "&Up"
        shortcut: "Ctrl+U"
        iconSource: "images/up.png"
        onTriggered: dirUp()
        tooltip: "Go up to the folder containing this one"
    }

    Rectangle {
        property int maxSize: Math.min(Screen.desktopAvailableWidth, Screen.desktopAvailableHeight)
        implicitWidth: Math.min(maxSize, Math.max(Screen.pixelDensity * 100, splitter.implicitWidth))
        implicitHeight: Math.min(maxSize, Screen.pixelDensity * 80)
        id: window
        color: root.palette.window

        Binding {
            target: root
            property: "folder"
            value: view.model.folder
        }
        Binding {
            target: view.model
            property: "folder"
            value: root.folder
        }
        Binding {
            target: currentPathField
            property: "text"
            value: root.urlToPath(root.folder)
        }
        Keys.onPressed: {
            event.accepted = true
            switch (event.key) {
            case Qt.Key_Back:
            case Qt.Key_Escape:
                reject()
                break
            default:
                event.accepted = false
                break
            }
        }

        SplitView {
            id: splitter
            x: 0
            width: parent.width
            anchors.top: titleBar.bottom
            anchors.bottom: bottomBar.top

            Column {
                id: sidebar
                Component.onCompleted: if (width < 1) width = sidebarSplitter.maxShortcutWidth
                height: parent.height
                width: 0 // initial width only; settings and onCompleted will override it
                SplitView {
                    id: sidebarSplitter
                    orientation: Qt.Vertical
                    property real rowHeight: 10
                    property real maxShortcutWidth: 50
                    width: parent.width
                    height: parent.height - favoritesButtons.height

                    ScrollView {
                        id: shortcuts
                        Component.onCompleted: {
                            if (height < 1)
                                height = shortcutsView.model.count * sidebarSplitter.rowHeight
                            Layout.minimumHeight = sidebarSplitter.rowHeight * 2.5
                        }
                        height: 0 // initial width only; settings and onCompleted will override it
                        ListView {
                            id: shortcutsView
                            model: root.shortcuts
                            anchors.bottomMargin: ControlsPrivate.Settings.hasTouchScreen ? Screen.pixelDensity * 3.5 : anchors.margins
                            implicitHeight: model.count * sidebarSplitter.rowHeight
                            delegate: Item {
                                id: shortcutItem
                                width: sidebarSplitter.width
                                height: shortcutLabel.implicitHeight * 1.5
                                Text {
                                    id: shortcutLabel
                                    text: shortcutsView.model[index]["name"]
                                    anchors {
                                        verticalCenter: parent.verticalCenter
                                        left: parent.left
                                        right: parent.right
                                        margins: 4
                                    }
                                    elide: Text.ElideLeft
                                    renderType: Text.NativeRendering
                                    Component.onCompleted: {
                                        sidebarSplitter.rowHeight = parent.height
                                        if (implicitWidth * 1.2 > sidebarSplitter.maxShortcutWidth)
                                            sidebarSplitter.maxShortcutWidth = implicitWidth * 1.2
                                    }
                                }
                                MouseArea {
                                    anchors.fill: parent
                                    onClicked: root.folder = shortcutsView.model[index]["url"]
                                }
                            }
                        }
                    }

                    ScrollView {
                        Layout.minimumHeight: sidebarSplitter.rowHeight * 2.5
                        ListView {
                            id: favorites
                            model: root.favoriteFolders
                            anchors.topMargin: ControlsPrivate.Settings.hasTouchScreen ? Screen.pixelDensity * 3.5 : anchors.margins
                            delegate: Item {
                                width: favorites.width
                                height: folderLabel.implicitHeight * 1.5
                                Text {
                                    id: folderLabel
                                    text: root.favoriteFolders[index]
                                    anchors {
                                        verticalCenter: parent.verticalCenter
                                        left: parent.left
                                        right: parent.right
                                        margins: 4
                                    }
                                    elide: Text.ElideLeft
                                    renderType: Text.NativeRendering
                                }
                                Menu {
                                    id: favoriteCtxMenu
                                    title: root.favoriteFolders[index]
                                    MenuItem {
                                        text: "Remove favorite"
                                        onTriggered: {
                                            root.favoriteFolders.splice(index, 1)
                                            favorites.model = root.favoriteFolders
                                        }
                                    }
                                }
                                MouseArea {
                                    id: favoriteArea
                                    anchors.fill: parent
                                    acceptedButtons: Qt.LeftButton | Qt.RightButton
                                    hoverEnabled: true
                                    onClicked: {
                                        if (mouse.button == Qt.LeftButton)
                                            root.folder = root.favoriteFolders[index]
                                        else if (mouse.button == Qt.RightButton)
                                            favoriteCtxMenu.popup()
                                    }
                                    onExited: ControlsPrivate.Tooltip.hideText()
                                    onCanceled: ControlsPrivate.Tooltip.hideText()
                                    Timer {
                                        interval: 1000
                                        running: favoriteArea.containsMouse && !favoriteArea.pressed && folderLabel.truncated
                                        onTriggered: ControlsPrivate.Tooltip.showText(favoriteArea,
                                                Qt.point(favoriteArea.mouseX, favoriteArea.mouseY), urlToPath(root.favoriteFolders[index]))
                                    }
                                }
                            }
                        }
                    }
                }

                Row {
                    id: favoritesButtons
                    height: plusButton.height
                    Button {
                        id: plusButton
                        text: "+"
                        width: height
                        onClicked: {
                            root.favoriteFolders.push(root.folder)
                            favorites.model = root.favoriteFolders
                        }
                    }
                }
            }

            TableView {
                id: view
                sortIndicatorVisible: true
                Layout.fillWidth: true
                Layout.minimumWidth: 40
                property bool needsWidthAdjustment: true
                selectionMode: root.selectMultiple ?
                    (ControlsPrivate.Settings.hasTouchScreen ? SelectionMode.MultiSelection : SelectionMode.ExtendedSelection) :
                    SelectionMode.SingleSelection
                onRowCountChanged: if (needsWidthAdjustment && rowCount > 0) {
                    resizeColumnsToContents()
                    needsWidthAdjustment = false
                }
                model: FolderListModel {
                    showFiles: !root.selectFolder
                    nameFilters: root.selectedNameFilterExtensions
                    sortField: (view.sortIndicatorColumn === 0 ? FolderListModel.Name :
                                (view.sortIndicatorColumn === 1 ? FolderListModel.Type :
                                (view.sortIndicatorColumn === 2 ? FolderListModel.Size : FolderListModel.LastModified)))
                    sortReversed: view.sortIndicatorOrder === Qt.DescendingOrder
                }

                onActivated: {
                    if (view.model.isFolder(row)) {
                        dirDown(view.model.get(row, "filePath"))
                    } else {
                        root.acceptSelection()
                    }
                }

                TableViewColumn {
                    id: fileNameColumn
                    role: "fileName"
                    title: "Filename"
                    delegate: Item {
                        implicitWidth: pathText.implicitWidth + pathText.anchors.leftMargin + pathText.anchors.rightMargin
                        Image {
                            id: fileIcon
                            width: height
                            x: 4
                            height: parent.height - 2
                            source: "images/folder.png"
                        }
                        Text {
                            id: pathText
                            text: styleData.value
                            onTextChanged: fileIcon.visible = view.model.isFolder(styleData.row)
                            anchors {
                                left: parent.left
                                right: parent.right
                                leftMargin: fileIcon.width + 8
                                rightMargin: 4
                                verticalCenter: parent.verticalCenter
                            }
                            color: styleData.textColor
                            elide: Text.ElideRight
                            renderType: Text.NativeRendering
                        }
                    }
                }
                TableViewColumn {
                    role: "fileSuffix"
                    title: "Type"
                    // TODO should not need to create a whole new component just to customize the text value
                    // something like textFormat: function(text) { return view.model.get(styleData.row, "fileIsDir") ? "folder" : text }
                    delegate: Item {
                        implicitWidth: sizeText.implicitWidth + sizeText.anchors.leftMargin + sizeText.anchors.rightMargin
                        Text {
                            id: sizeText
                            text: view.model.get(styleData.row, "fileIsDir") ? "folder" : styleData.value
                            anchors {
                                left: parent.left
                                right: parent.right
                                leftMargin: 4
                                rightMargin: 4
                                verticalCenter: parent.verticalCenter
                            }
                            color: styleData.textColor
                            elide: Text.ElideRight
                            renderType: Text.NativeRendering
                        }
                    }
                }
                TableViewColumn {
                    role: "fileSize"
                    title: "Size"
                    horizontalAlignment: Text.AlignRight
                }
                TableViewColumn { role: "fileModified" ; title: "Modified" }
                TableViewColumn { role: "fileAccessed" ; title: "Accessed" }
            }
        }

        ToolBar {
            id: titleBar
            RowLayout {
                width: parent.width
                ToolButton {
                    iconSource: "images/up.png"
                    action: dirUpAction
                }
                TextField {
                    id: currentPathField
                    Layout.fillWidth: true
                    onAccepted: {
                        root.clearSelection()
                        if (root.addSelection(root.pathToUrl(text)))
                            root.accept()
                        else
                            root.folder = root.pathFolder(text)
                    }
                }
            }
        }
        Item {
            id: bottomBar
            width: parent.width
            height: buttonRow.height + buttonRow.spacing * 2
            anchors.bottom: parent.bottom

            Row {
                id: buttonRow
                anchors.right: parent.right
                anchors.rightMargin: spacing
                anchors.verticalCenter: parent.verticalCenter
                spacing: 4
                ComboBox {
                    id: filterField
                    model: root.nameFilters
                    visible: !selectFolder
                    width: bottomBar.width - cancelButton.width - okButton.width - parent.spacing * 5
                    anchors.verticalCenter: parent.verticalCenter
                    onCurrentTextChanged: {
                        root.selectNameFilter(currentText)
                        view.model.nameFilters = root.selectedNameFilterExtensions
                    }
                }
                Button {
                    id: cancelButton
                    text: "Cancel"
                    onClicked: root.reject()
                }
                Button {
                    id: okButton
                    text: "OK"
                    onClicked: {
                        if (view.model.isFolder(view.currentIndex) && !selectFolder)
                            dirDown(view.model.get(view.currentIndex, "filePath"))
                        else
                            root.acceptSelection()
                    }
                }
            }
        }
    }
}
