import QtQuick 2.14
import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14
import QtQuick.Scene3D 2.14
import Qt3D.Core 2.14
import Qt3D.Render 2.14
import Qt3D.Input 2.14
import Qt3D.Extras 2.14

import QtQuick 2.14 as QQ2

Entity {
    Material {
        id: pointxyziMaterial
        property vector3d colorBound: Qt.vector3d( 0.1, 0.3, 0.6)
        readonly property int intensityColorMode: 0
        readonly property int distanceColorMode: 1
        property int colorMode: intensityColorMode
        property real pointSize: 2.0
        effect: Effect {
            id: pointxyzi_effect
            parameters: [
                Parameter { name: "xyz"; value: Qt.vector3d( 0.0, 0.0, 0.0) },
                Parameter { name: "i"; value: 1.0 },
                Parameter { name: "color_mode"; value: pointxyziMaterial.colorMode },
                Parameter { name: "max_distance"; value: 300.0 },
                Parameter { name: "color_bound"; value: pointxyziMaterial.colorBound }
            ]
            techniques: [
                Technique {
                    graphicsApiFilter {
                        api: GraphicsApiFilter.OpenGL
                        profile: GraphicsApiFilter.CoreProfile
                        majorVersion: 3
                        minorVersion: 0
                    }

                    filterKeys: [ FilterKey { name: "renderingStyle"; value: "forward" } ]

                    renderPasses: [
                        RenderPass {
                            shaderProgram: ShaderProgram {
                                id: pointxyziShader
                                vertexShaderCode:   loadSource("file:glsl/pointxyzi.vert")
                                fragmentShaderCode: loadSource("file:glsl/pointxyzi.frag")
                            }
                            renderStates: [
                                DepthTest { depthFunction: DepthTest.Less },
                                // BlendEquationArguments {
                                //     sourceRgb: BlendEquationArguments.One
                                //     destinationRgb: BlendEquationArguments.Zero
                                // },
                                PointSize {
                                    sizeMode: PointSize.Fixed
                                    value: pointxyziMaterial.pointSize
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    }
    GeometryRenderer {
        id: pointxyziGeometryRenderer
        primitiveType: modelData.useAlgo ? GeometryRenderer.Triangles : GeometryRenderer.Points
        geometry: modelData.useAlgo ? triangleGeometry : pointxyziGeometry
        Geometry {
            id: pointxyziGeometry
            boundingVolumePositionAttribute: position
            attributes: [position, intensity]
        }
        Geometry {
            id: triangleGeometry
            boundingVolumePositionAttribute: position
            attributes: [position, intensity, triangle_indexes]
        }
        Attribute {
            id: position
            attributeType: Attribute.VertexAttribute
            vertexBaseType: Attribute.Float
            vertexSize: 3
            count: modelData.primitiveCount
            byteOffset: 0
            byteStride: 4 * 4 // 1 vertex (=3 coordinates) * sizeof(float)
            name: "xyz"
            buffer: vertexBuffer
        }
        Attribute {
            id: intensity
            attributeType: Attribute.VertexAttribute
            vertexBaseType: Attribute.Float
            vertexSize: 1
            count: modelData.primitiveCount
            byteOffset: 3 * 4
            byteStride: 4 * 4 // 1 vertex (=3 coordinates) * sizeof(float)
            name: "i"
            buffer: vertexBuffer
        }
        Attribute {
            id: triangle_indexes
            attributeType: Attribute.IndexAttribute
            vertexBaseType: Attribute.UnsignedInt
            vertexSize: 1
            count: modelData.primitiveCount * 3
            byteOffset: 0
            byteStride: 1 * 4 // 1 index * sizeof(Uint32)
            buffer: indexBuffer
        }
        Buffer {
            id: vertexBuffer
            data: {
                // Dirty code: explicitly call garbage collection function
                gc()
                // Dirty code: prevent memory growth for modelData.data
                return modelData.vertex
            }
        }
        Buffer {
            id: indexBuffer
            data: {
                // Dirty code: explicitly call garbage collection function
                gc()
                // Dirty code: prevent memory growth for modelData.data
                return modelData.index
            }
        }
    }
    Transform {
        id: pointxyziTransform
    }
    ObjectPicker {
        id: pointxyziPicker
        property bool picking: true
        onPressed: {
            picking = true
            console.log("point: (" + pick.localIntersection.x + ", " + pick.localIntersection.y + ", " + pick.localIntersection.z + ")")
            console.log("point distance: " + Number(pick.localIntersection.length()))
        }
        function setColorMode( colorModeText ) {
            if (colorModeText == "Intensity") {
                pointxyziMaterial.colorMode = pointxyziMaterial.intensityColorMode
            } else if (colorModeText == "Distance") {
                pointxyziMaterial.colorMode = pointxyziMaterial.distanceColorMode
            }
        }
        function setColorBound ( colorBound ) {
            pointxyziMaterial.colorBound = colorBound
        }
        function setPointSize ( pointSize ) {
            pointxyziMaterial.pointSize = pointSize
        }
        // function setUseAlgo( useAlgo ) {
        //     modelData.useAlgo = useAlgo
        // }
        // function setDs0(ds0) {
        //     modelData.ds0 = ds0
        // }
        // function setZ0(z0) {
        //     modelData.z0 = z0
        // }
        // function setK0(k0) {
        //     modelData.k0 = k0
        // }
        // function setC0(c0) {
        //     modelData.c0 = c0
        // }
    }
    MouseHandler {
        id: pointxyziMouseHandler
        sourceDevice: mouseDevice
        onWheel: {}
    }
    components: [pointxyziMaterial, pointxyziGeometryRenderer, pointxyziTransform, pointxyziPicker, pointxyziMouseHandler]

    ColumnLayout {
        id: pointxyziHUD
        property alias picker: pointxyziPicker
        parent: picker.picking ? hud : invisibleHUD
        Button {
            text: "PointXYZIAlgo"
            onClicked: parent.picker.picking = false
        }
        ColumnLayout {
            Label {
                text: "Color Mode"
                color: activePalette.windowText
            }
            ComboBox {
                editable: false
                model: ListModel {
                    id: model
                    ListElement { text: "Intensity" }
                    ListElement { text: "Distance" }
                }
                onActivated: {
                    pointxyziHUD.picker.setColorMode(currentText)
                }
            }
        }
        ColumnLayout {
            Label {
                text: "Color Bound"
                color: activePalette.windowText
            }
            Slider {
                id: boundGSlider
                from: 0
                value: 0.1
                to: 1
                implicitHeight: 12
                background: Rectangle {
                    implicitWidth: 128
                    color: "green"
                }
                onMoved: {
                    if (boundGSlider.value > boundBSlider.value) {
                        boundBSlider.value = boundGSlider.value
                        if (boundBSlider.value > boundRSlider.value) {
                            boundRSlider.value = boundBSlider.value
                        }
                    }
                    pointxyziHUD.picker.setColorBound(Qt.vector3d(boundGSlider.value, boundBSlider.value, boundRSlider.value))
                }
            }
            Slider {
                id: boundBSlider
                from: 0
                value: 0.3
                to: 1
                implicitHeight: 12
                background: Rectangle {
                    implicitWidth: 128
                    color: "blue"
                }
                onMoved: {
                    if (boundBSlider.value < boundGSlider.value) {
                        boundGSlider.value = boundBSlider.value
                    }
                    if (boundBSlider.value > boundRSlider.value) {
                        boundRSlider.value = boundBSlider.value
                    }
                    pointxyziHUD.picker.setColorBound(Qt.vector3d(boundGSlider.value, boundBSlider.value, boundRSlider.value))
                }
            }
            Slider {
                id: boundRSlider
                from: 0
                value: 0.6
                to: 1
                implicitHeight: 12
                background: Rectangle {
                    implicitWidth: 128
                    color: "red"
                }
                onMoved: {
                    if (boundRSlider.value < boundBSlider.value) {
                        boundBSlider.value = boundRSlider.value
                        if (boundBSlider.value < boundGSlider.value) {
                            boundGSlider.value = boundBSlider.value
                        }
                    }
                    pointxyziHUD.picker.setColorBound(Qt.vector3d(boundGSlider.value, boundBSlider.value, boundRSlider.value))
                }
            }
        }
        ColumnLayout {
            Label {
                text: "Point Size"
                color: activePalette.windowText
            }
            SpinBox {
                from: 1
                to: 10
                value: 2
                onValueModified: {
                    pointxyziHUD.picker.setPointSize(value)
                }
            }
        }
        // CheckBox {
        //     checked: false
        //     text: "Use Algo"
        //     background: Rectangle {
        //         implicitWidth: 36
        //         implicitHeight: 36
        //         color: "#e0e0e0"
        //     }
        //     nextCheckState: function() {
        //         if (checkState == Qt.Unchecked) {
        //             parent.picker.setUseAlgo(true)
        //             return Qt.Checked
        //         } else {
        //             parent.picker.setUseAlgo(false)
        //             return Qt.Unchecked
        //         }
        //     }
        // }
        // SpinBox {
        //     from: 10
        //     to: 100
        //     stepSize: 10
        //     value: 50
        //     onValueModified: {
        //         parent.picker.setDs0(value / 100.0)
        //     }
        // }
        // SpinBox {
        //     from: -300
        //     to: 0
        //     stepSize: 10
        //     value: -160
        //     onValueModified: {
        //         parent.picker.setZ0(value / 100.0)
        //     }
        // }
        // SpinBox {
        //     from: 0
        //     to: 30
        //     stepSize: 1
        //     value: 15
        //     onValueModified: {
        //         parent.picker.setK0(value / 100.0)
        //     }
        // }
        // SpinBox {
        //     from: 0
        //     to: 1000
        //     stepSize: 10
        //     value: 500
        //     onValueModified: {
        //         parent.picker.setC0(value / 100.0)
        //     }
        // }
    }
}
