import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import FluentUI 1.0

Item {
    property int tabWidthBehavior : FluTabViewType.Equal
    property int closeButtonVisibility : FluTabViewType.Always
    property int itemWidth: 146
    property bool addButtonVisibility: true
    signal newPressed
    id:control
    implicitHeight: height
    implicitWidth: width
    anchors.fill: {
        if(parent)
            return parent
        return undefined
    }
    QtObject {
        id: d
        property int dragIndex: -1
        property bool dragBehavior: false
        property bool itemPress: false
        property int maxEqualWidth: 240
    }
    MouseArea{
        anchors.fill: parent
        preventStealing: true
    }
    ListModel{
        id:tab_model
    }
    FluIconButton{
        id:btn_new
        visible: addButtonVisibility
        width: 34
        height: 34
        x:Math.min(tab_nav.contentWidth,tab_nav.width)
        anchors.top: parent.top
        iconSource: FluentIcons.Add
        onClicked: {
            newPressed()
        }
    }
    ListView{
        id:tab_nav
        height: 34
        orientation: ListView.Horizontal
        anchors{
            top: parent.top
            left: parent.left
            right: parent.right
            rightMargin: 34
        }
        interactive: false
        model: tab_model
        move: Transition {
            NumberAnimation { properties: "x"; duration: 100; easing.type: Easing.OutCubic }
            NumberAnimation { properties: "y"; duration: 100; easing.type: Easing.OutCubic }
        }
        moveDisplaced: Transition {
            NumberAnimation { properties: "x"; duration: 300; easing.type: Easing.OutCubic}
            NumberAnimation { properties: "y"; duration: 100;  easing.type: Easing.OutCubic }
        }
        clip: true
        ScrollBar.horizontal: ScrollBar{
            id: scroll_nav
            policy: ScrollBar.AlwaysOff
        }
        delegate:  Item{
            width: item_layout.width
            height: item_container.height
            z: item_mouse_drag.pressed ? 1000 : 1
            Item{
                id:item_layout
                width: item_container.width
                height: item_container.height
                Item{
                    id:item_container
                    property real timestamp: new Date().getTime()
                    height: tab_nav.height
                    width: {
                        if(tabWidthBehavior === FluTabViewType.Equal){
                            return Math.max(Math.min(d.maxEqualWidth,tab_nav.width/tab_nav.count),41 + item_btn_close.width)
                        }
                        if(tabWidthBehavior === FluTabViewType.SizeToContent){
                            return itemWidth
                        }
                        if(tabWidthBehavior === FluTabViewType.Compact){
                            return item_mouse_hove.containsMouse || item_btn_close.hovered || tab_nav.currentIndex === index  ? itemWidth : 41 + item_btn_close.width
                        }
                        return Math.max(Math.min(d.maxEqualWidth,tab_nav.width/tab_nav.count),41 + item_btn_close.width)
                    }
                    Behavior on x { enabled: d.dragBehavior; NumberAnimation { duration: 200 } }
                    Behavior on y { enabled: d.dragBehavior; NumberAnimation { duration: 200 } }
                    MouseArea{
                        id:item_mouse_hove
                        anchors.fill: parent
                        hoverEnabled: true
                    }
                    FluTooltip{
                        visible: item_mouse_hove.containsMouse
                        text:item_text.text
                        delay: 1000
                    }
                    MouseArea{
                        id:item_mouse_drag
                        anchors.fill: parent
                        drag.target: item_container
                        drag.axis: Drag.XAxis
                        onWheel: (wheel)=>{
                                     if (wheel.angleDelta.y > 0) scroll_nav.decrease()
                                     else scroll_nav.increase()
                                 }
                        onPressed: {
                            d.itemPress = true
                            item_container.timestamp = new Date().getTime();
                            d.dragBehavior = false;
                            var pos = tab_nav.mapFromItem(item_container, 0, 0)
                            d.dragIndex = model.index
                            item_container.parent = tab_nav
                            item_container.x = pos.x
                            item_container.y = pos.y
                        }
                        onReleased: {
                            d.itemPress = false
                            timer.stop()
                            var timeDiff = new Date().getTime() - item_container.timestamp
                            if (timeDiff < 300) {
                                tab_nav.currentIndex = index
                            }
                            d.dragIndex = -1;
                            var pos = tab_nav.mapToItem(item_layout, item_container.x, item_container.y)
                            item_container.parent = item_layout;
                            item_container.x = pos.x;
                            item_container.y = pos.y;
                            d.dragBehavior = true;
                            item_container.x = 0;
                            item_container.y = 0;
                        }
                        onPositionChanged: {
                            var pos = tab_nav.mapFromItem(item_container, 0, 0)
                            updatePosition(pos)
                            if(pos.x<0){
                                timer.isIncrease = false
                                timer.restart()
                            }else if(pos.x>tab_nav.width-itemWidth){
                                timer.isIncrease = true
                                timer.restart()
                            }else{
                                timer.stop()
                            }
                        }
                        Timer{
                            id:timer
                            property bool isIncrease: true
                            interval: 10
                            repeat: true
                            onTriggered: {
                                if(isIncrease){
                                    if(tab_nav.contentX>=tab_nav.contentWidth-tab_nav.width){
                                        return
                                    }
                                    tab_nav.contentX = tab_nav.contentX+2
                                }else{
                                    if(tab_nav.contentX<=0){
                                        return
                                    }
                                    tab_nav.contentX = tab_nav.contentX-2
                                }
                                item_mouse_drag.updatePosition(tab_nav.mapFromItem(item_container, 0, 0))
                            }
                        }
                        function updatePosition(pos){
                            var idx = tab_nav.indexAt(pos.x+tab_nav.contentX+1, pos.y)
                            if(idx<0){
                                return
                            }
                            if(idx>=tab_nav.count){
                                return
                            }
                            if (d.dragIndex !== idx) {
                                tab_model.move(d.dragIndex, idx, 1)
                                d.dragIndex = idx;
                            }
                        }
                    }
                    FluRectangle{
                        anchors.fill: parent
                        radius: [6,6,0,0]
                        color: {
                            if(item_mouse_hove.containsMouse || item_btn_close.hovered){
                                return FluTheme.itemHoverColor
                            }
                            if(tab_nav.currentIndex === index){
                                return FluTheme.itemCheckColor
                            }
                            return FluTheme.itemNormalColor
                        }
                    }
                    RowLayout{
                        spacing: 0
                        height: parent.height
                        Image{
                            source:model.icon
                            Layout.leftMargin: 10
                            Layout.preferredWidth: 14
                            Layout.preferredHeight: 14
                            Layout.alignment: Qt.AlignVCenter
                        }
                        FluText{
                            id:item_text
                            text: model.text
                            Layout.leftMargin: 10
                            visible: {
                                if(tabWidthBehavior === FluTabViewType.Equal){
                                    return true
                                }
                                if(tabWidthBehavior === FluTabViewType.SizeToContent){
                                    return true
                                }
                                if(tabWidthBehavior === FluTabViewType.Compact){
                                    return item_mouse_hove.containsMouse || item_btn_close.hovered || tab_nav.currentIndex === index
                                }
                                return false
                            }
                            Layout.preferredWidth: visible?item_container.width - 41 - item_btn_close.width:0
                            elide: Text.ElideRight
                            Layout.alignment: Qt.AlignVCenter
                        }
                    }
                    FluIconButton{
                        id:item_btn_close
                        iconSource: FluentIcons.ChromeClose
                        iconSize: 10
                        width: visible ? 24 : 0
                        height: 24
                        visible: {
                            if(closeButtonVisibility === FluTabViewType.Never)
                                return false
                            if(closeButtonVisibility === FluTabViewType.OnHover)
                                return item_mouse_hove.containsMouse || item_btn_close.hovered
                            return true
                        }
                        anchors{
                            right: parent.right
                            rightMargin: 5
                            verticalCenter: parent.verticalCenter
                        }
                        onClicked: {
                            tab_model.remove(index)
                        }
                    }
                    FluDivider{
                        width: 1
                        height: 16
                        orientation: Qt.Vertical
                        anchors{
                            verticalCenter: parent.verticalCenter
                            right: parent.right
                        }
                    }
                }
            }
        }
    }
    Item{
        id:container
        anchors{
            top: tab_nav.bottom
            left: parent.left
            right: parent.right
            bottom: parent.bottom
        }
        Repeater{
            model:tab_model
            FluLoader{
                property var argument: model.argument
                anchors.fill: parent
                sourceComponent: model.page
                visible: tab_nav.currentIndex === index
            }
        }
    }
    function createTab(icon,text,page,argument={}){
        return {icon:icon,text:text,page:page,argument:argument}
    }
    function appendTab(icon,text,page,argument){
        tab_model.append(createTab(icon,text,page,argument))
    }
    function setTabList(list){
        tab_model.clear()
        tab_model.append(list)
    }
    function count(){
        return tab_nav.count
    }
}
