// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers
import QtQuick3D.Physics
import QtQuick3D.Physics.Helpers as Helpers
import QtQuick3D.Xr
import QtQuick3D.Particles3D

XrView {
    id: xrView
    XrErrorDialog { id: err }
    onInitializeFailed: (errorString) => err.run("XR physics-base teleportation", errorString)
    referenceSpace: XrView.ReferenceSpaceStage

    environment: ExtendedSceneEnvironment {
        id: extendedSceneEnvironment
        backgroundMode: SceneEnvironment.Color
        probeExposure: 0.7
        lightProbe: Texture {
            source: "media/textures/OpenfootageNET_lowerAustria01-1024.hdr"
        }
        skyboxBlurAmount: 0.0
        specularAAEnabled: true
        clearColor: theFog.color
        exposure: teleporter.screenVisibility

        fog: Fog {
            id: theFog
            color:"gray"
            enabled: true
            depthEnabled: true
            depthNear: 1500
            depthFar: 3000
        }
    }

    Component.onCompleted: {
        ParticleResources.init(xrView)
    }

    xrOrigin: XrOrigin {
        id: xrOrigin

        camera: XrCamera {
            id: trackingCamera
            Prompter {
                id: prompter
            }
        }

        XrController {
            id: xrLeftController
            controller: XrController.ControllerLeft
            poseSpace: XrController.AimPose

            TorchGripper {
                hand: XrInputAction.LeftHand
            }
        }

        XrController {
            id: xrRightController
            controller: XrController.ControllerRight
            poseSpace: XrController.AimPose

            XrInputAction {
                id: thumbstickX
                hand: XrInputAction.RightHand
                actionId: [XrInputAction.ThumbstickX]
            }

            XrInputAction {
                id: thumbstickY
                hand: XrInputAction.RightHand
                actionId: [XrInputAction.ThumbstickY]
            }

            XrInputAction {
                id: trackpadX
                hand: XrInputAction.RightHand
                actionId: [XrInputAction.TrackpadX]
            }

            XrInputAction {
                id: trackpadY
                hand: XrInputAction.RightHand
                actionId: [XrInputAction.TrackpadY]
            }

            XrInputAction {
                id: trackpadPressed
                hand: XrInputAction.RightHand
                actionId: [XrInputAction.TrackpadPressed]
            }

            TorchGripper {
                hand: XrInputAction.RightHand
            }

            property real xValue: trackpadPressed.pressed ? trackpadX.value : thumbstickX.value
            property real yValue: trackpadPressed.pressed ? trackpadY.value : thumbstickY.value
        }
    }

    PhysicsbaseTeleporter {
        id: teleporter
        rayPicker: xrView
        cameraOrigin: xrOrigin
        camera: xrOrigin.camera
        beamHandle: xrRightController
        characterController: character
        xStickValue: xrRightController.xValue
        yStickValue: xrRightController.yValue
        onDoTeleportation: (cameraOriginPosition, characterControllerPosition)=> {
                               xrOrigin.position = cameraOriginPosition
                               character.teleport(characterControllerPosition)
                           }
        onDoRotation: (cameraOriginRotation, cameraOriginPosition)=> {
                          xrOrigin.rotation = cameraOriginRotation
                          xrOrigin.position = cameraOriginPosition
                      }
    }

    PhysicsWorld {
        id: physicsWorld
        running: true
        scene: xrView
        gravity: Qt.vector3d(0, -981, 0)
    }

    CharacterController {
        id: character
        property bool inTheHouse: true
        signal enteredTheHouse
        signal leftTheHouse

        onEnteredTheHouse: {
            inTheHouse = true
        }
        onLeftTheHouse: {
            inTheHouse = false
        }

        property vector3d startPos: Qt.vector3d(0, 200, 0)
        scale: Qt.vector3d(0.5, 1.75, 0.5)
        Component.onCompleted: {
            prompter.prompt = Prompter.DarknessFalling
            prompter.prompt = Prompter.PickupTorch
            teleporter.teleportTo(character.startPos)
        }

        collisionShapes: CapsuleShape {
            id: capsuleShape
        }

        onShapeHit: (body, position, impulse, normal)=>{
                        if (body.objectName === "Ground")
                        leftTheHouse()
                        else if (body.objectName === "HouseFloor")
                        enteredTheHouse()
                    }

        enableShapeHitCallback: true
        sendTriggerReports: true
        gravity: physicsWorld.gravity.times(10) //make it fall faster
    }

    Ground {

    }

    Fence {

    }

    House {

    }

    Chair {
        eulerRotation: Qt.vector3d(0, -45, 0)
        position: Qt.vector3d(-200, 200, -300)
    }

    Table {
        position: Qt.vector3d(-30, 200, -300)
    }

    Torch {
        id: torch
        position: Qt.vector3d(0, 350, -300)
        eulerRotation: Qt.vector3d(-90, 0, 0)
        windEnabled: !character.inTheHouse

        onAttachedToChanged: {
            if (attachedTo)
                prompter.prompt = Prompter.LightupTorch
        }

        onIsOnChanged: {
            prompter.prompt = Prompter.DefendCrop
        }
    }

    Grass {
        id: field
        z: -1200
    }

    Stands {

    }

    Campfire {
        id: campFire1
        position: Qt.vector3d(1000, 185 ,1000)
        function updateColors(){
            if (campFire1.isOn && campFire2.isOn &&
                    campFire3.isOn && campFire4.isOn) {
                campFire1.fireColor = "white"
                campFire1.lightColor = Qt.lighter("orange", 1.5)
                enemy.run = true
            }else {
                campFire1.fireColor = "orange"
                campFire1.lightColor = "orange"
                enemy.run = false
            }

            campFire2.fireColor = campFire1.fireColor
            campFire2.lightColor = campFire1.lightColor
            campFire3.fireColor = campFire1.fireColor
            campFire3.lightColor = campFire1.lightColor
            campFire4.fireColor = campFire1.fireColor
            campFire4.lightColor = campFire1.lightColor
        }
        onIsOnChanged: {
            campFire1.updateColors()
        }
    }

    Campfire {
        id: campFire2
        position: Qt.vector3d(1000, 185 ,-1000)
        onIsOnChanged: {
            campFire1.updateColors()
        }
    }

    Campfire {
        id: campFire3
        position: Qt.vector3d(-1000, 185 ,1000)
        onIsOnChanged: {
            campFire1.updateColors()
        }
    }

    Campfire {
        id: campFire4
        position: Qt.vector3d(-1000, 185 ,-1000)
        onIsOnChanged: {
            campFire1.updateColors()
        }
    }

    Smoke {
        id: enemy
        readonly property real maxY: 5000
        readonly property real startY: 40000
        property bool run: false
        position: Qt.vector3d(0, startY, 0)
        color: "black"
        colorVariation: 0.0
        size: run ? 6.0 : 4.0

        FrameAnimation {
            running: true
            property real time: 0
            property real fieldEncounterTime: 0
            onTriggered: {
                time += 0.5 * frameTime
                let enemyLinearY = enemy.scenePosition.y / enemy.maxY
                let enemyOffset = enemyLinearY * 5000 + 200
                let targetBase = field.scenePosition
                let enemyMovementSpeed = 20.
                let chaseTheCamera = false

                if (fieldEncounterTime > 0.99 && !character.inTheHouse && !enemy.run) {
                    targetBase = xrOrigin.camera.scenePosition
                    enemyOffset = 20
                    chaseTheCamera = true
                    enemyMovementSpeed = 5
                }

                let target = Qt.vector3d(targetBase.x + Math.cos(time) * enemyOffset ,
                                         targetBase.y + Math.abs(Math.cos(time)) * 100,
                                         targetBase.z + Math.sin(time) * enemyOffset)
                if (torch.isOn) {
                    let enemyToTorchDir =  torch.scenePosition.minus(enemy.position)
                    let enemyToTorchLen = enemyToTorchDir.length()
                    let dis = Math.max(0, 500 - enemyToTorchLen)
                    target.y += dis * dis * dis
                }

                if (enemy.run)
                    target.y += enemy.maxY

                if (!chaseTheCamera) {
                    field.baseColor = ""

                    if (field.scenePosition.minus(enemy.scenePosition).length() < 500)
                        fieldEncounterTime += frameTime * 0.02
                    else
                        fieldEncounterTime -= frameTime * 0.01

                    fieldEncounterTime = Math.min(Math.max(fieldEncounterTime, 0), 1.)

                    field.baseColor = Qt.darker("white", Math.exp(fieldEncounterTime))
                }

                let enemyToTargetDir = target.minus(enemy.scenePosition).normalized().times(enemyMovementSpeed)
                enemy.position = enemy.scenePosition.plus(enemyToTargetDir)
            }
        }
    }
}
