import RapierBody from '@RE/RogueEngine/rogue-rapier/Components/RapierBody.re';
import GetForwardVector from 'Assets/Library/GetForwardVector';
import * as RE from 'rogue-engine';
import * as THREE from 'three'

export default class ShipCannonController extends RE.Component {
  @RE.props.prefab() cannonball: RE.Prefab
  objectVectorCalculator: GetForwardVector

  @RE.props.list.audio(true) cannonShotSounds: THREE.Audio[] = []

  @RE.props.checkbox() debug: boolean = false

  @RE.props.object3d() positionObject

  delayedActionQueue:Function[] = []

  lines = new THREE.LineSegments(
    new THREE.BufferGeometry(),
    new THREE.LineBasicMaterial({ color: new THREE.Color("#00FF00") })
  );

  shotIterator = 0

  @RE.props.checkbox() fireLeft = false
  @RE.props.checkbox() fireRight = false
  @RE.props.checkbox() fireForward = false

  awake() {
    
    if(!this.positionObject) {
      this.positionObject = this.object3d.parent
    }
    this.objectVectorCalculator = new GetForwardVector(this.positionObject)

    if(this.debug) {
      this.lines.frustumCulled = false;
      RE.App.currentScene.remove(this.lines);

      this.lines.userData.isEditorObject = true;
      RE.App.currentScene.add(this.lines);
    }
  }

  start() {

  }

  update() {
    this.delayedActionQueue.forEach((action) => {
      action()
    })
    this.delayedActionQueue = []
    const powderStrength = 50
    const forwardVector = this.objectVectorCalculator.getForward().clone().normalize()
    const rightVector = this.objectVectorCalculator.getRight().clone().normalize()
    if(this.debug) {
      this.lines.visible = false
    }
    const worldPosition = this.positionObject.position ?? new THREE.Vector3(0,0,0)
    const forwardLaunchPosition = forwardVector.clone().multiplyScalar(3.8)
    const shiftedForward = forwardVector.clone().multiplyScalar(1.38)
    const shiftedOutward = rightVector.clone().multiplyScalar(0.1)
    const rightLaunchPosition = rightVector.clone().add(shiftedOutward).add(shiftedForward)
    const leftLaunchPosition = rightVector.clone().add(shiftedOutward).negate().add(shiftedForward)
    const verticalOffset = new THREE.Vector3(0,1.8,0)

    if(this.fireForward) {
      let forwardCannonball = this.cannonball.instantiate()
      
      forwardCannonball.position.set(forwardLaunchPosition.x,forwardLaunchPosition.y,forwardLaunchPosition.z).add(verticalOffset).add(worldPosition)

      let forwardCannonballBody = RE.getObjectComponents(forwardCannonball).filter(component => component instanceof RapierBody)[0] as RapierBody
      if(forwardCannonballBody){
        this.delayedActionQueue.push(() => {
          this.playShotSound(forwardCannonball)
        forwardCannonballBody.body.applyImpulse(forwardVector.clone().multiplyScalar(powderStrength).multiplyScalar(RE.Runtime.deltaTime), true)
        this.fireForward = false
        })
      } else {
        RE.Debug.logWarning("forward cannon body not loaded yet")
      }
    }

    if(this.fireRight) {
      let rightCannonball = this.cannonball.instantiate()
      
      rightCannonball.position.set(rightLaunchPosition.x,rightLaunchPosition.y,rightLaunchPosition.z).add(verticalOffset).add(worldPosition)

      let rightCannonballBody = RE.getObjectComponents(rightCannonball).filter(component => component instanceof RapierBody)[0] as RapierBody
      if(rightCannonballBody){
        this.delayedActionQueue.push(() => {
          this.playShotSound(rightCannonball)
          rightCannonballBody.body.applyImpulse(rightVector.clone().multiplyScalar(powderStrength).multiplyScalar(RE.Runtime.deltaTime), true)
          this.fireRight = false
        })
      } else {
        RE.Debug.logWarning("right cannon body not loaded yet")
      }
    }

    if(this.fireLeft) {
      let leftCannonball = this.cannonball.instantiate()
      
      leftCannonball.position.set(leftLaunchPosition.x,leftLaunchPosition.y,leftLaunchPosition.z).add(verticalOffset).add(worldPosition)

      let leftCannonballBody = RE.getObjectComponents(leftCannonball).filter(component => component instanceof RapierBody)[0] as RapierBody
      if(leftCannonballBody){
        this.delayedActionQueue.push(() => {
          this.playShotSound(leftCannonball)
          leftCannonballBody.body.applyImpulse(rightVector.clone().negate().multiplyScalar(powderStrength).multiplyScalar(RE.Runtime.deltaTime), true)
          this.fireLeft = false
        })
      } else {
        RE.Debug.logWarning("left cannon body not loaded yet")
      }
    }
    

    if(this.debug)
{
    this.lines.visible = true

    let vertexes = new Float32Array([
      ...worldPosition.clone().add(verticalOffset).toArray(),
      ...forwardLaunchPosition.clone().add(worldPosition).add(verticalOffset).toArray(),
      ...worldPosition.clone().add(verticalOffset).add(shiftedForward).toArray(),
      ...rightLaunchPosition.clone().add(verticalOffset).add(worldPosition).toArray(),
      ...worldPosition.clone().add(verticalOffset).add(shiftedForward).toArray(),
      ...leftLaunchPosition.clone().add(verticalOffset).add(worldPosition).toArray()
    ])
    this.lines.geometry.setAttribute(
      "position",
      new THREE.BufferAttribute(vertexes, 3),
    )
}
  }

  playShotSound(target) {
    if(this.cannonShotSounds.length > 0) {
      let randomSound = this.cannonShotSounds[this.shotIterator++]
      target.add(randomSound)
      randomSound.setVolume(10)
      randomSound.play()
    }

    if(this.shotIterator >= this.cannonShotSounds.length) {
      this.shotIterator = 0
    }
  }
}

RE.registerComponent(ShipCannonController);
        