import RapierBody from '@RE/RogueEngine/rogue-rapier/Components/RapierBody.re'
import * as RE from 'rogue-engine'
import * as THREE from 'three'
import * as RAPIER from '@dimforge/rapier3d-compat'
import RapierCollider from '@RE/RogueEngine/rogue-rapier/Components/Colliders/RapierCollider'
import RapierConfig from '@RE/RogueEngine/rogue-rapier/Components/RapierConfig.re'

export default class ObjectSpinner extends RE.Component {
  @RE.props.num() rotationSpeed = 1
  @RE.props.vector3() rotationAxis = new THREE.Vector3(0,1,0)
  @RE.props.checkbox() useObjectUp = true
  rapierConfig: RapierConfig
  rapierBodyComponent: RapierBody
  rotation = 0
  position = 1
  awake() {
  }

  start() {
    this.rapierConfig = RE.getComponent(RapierConfig) as RapierConfig
    let allBodies = this.getRapierBodyComponentsFromChildren()
    if(allBodies.length > 0) {
      this.rapierBodyComponent = allBodies[0]
    }
  }
  
  getRapierBodyComponentsFromChildren() {
    let bodies: RapierBody[] = []
    this.object3d.traverse(obj => {
      const components = RE.getObjectComponents(obj);

      components.forEach(comp => {
        if (comp instanceof RapierBody) {
          bodies.push(comp);
        }
      });
    });
    return bodies
  }

  update() {
    if(this.useObjectUp) {
      this.rotationAxis = this.object3d.up
    }

    if(this.rapierBodyComponent) {
      if (!this.rapierBodyComponent.body) {
        RE.Debug.logWarning("No character body")
        return
      }
  
      if (this.rapierBodyComponent.body.numColliders() < 1) {
        RE.Debug.logWarning("No character collider")
        return
      }

      const nextRotation = this.convertRapierToThree(this.rapierBodyComponent.body.rotation())
      const newRotation = this.quaternionFromAxisAngle(this.rotationAxis, this.rotationSpeed / 1000)
      nextRotation.multiply(newRotation)
      this.rapierBodyComponent.body.setNextKinematicRotation(nextRotation)
      
    } else {
      this.object3d.rotateOnAxis(this.rotationAxis, this.rotationSpeed / 1000)
    }
    
  }

  convertRapierToThree(oldQuaternion: RAPIER.Quaternion) {
    return new THREE.Quaternion(oldQuaternion.x, oldQuaternion.y, oldQuaternion.z, oldQuaternion.w)
  }

  quaternionFromAxisAngle(axis, rotationRadians) {
    let factor = Math.sin(rotationRadians / 2)
    let x = axis.x * factor
    let y = axis.y * factor
    let z = axis.z * factor
    let w = Math.cos(rotationRadians / 2)
    let normalized = new THREE.Quaternion(x, y, z, w).normalize()
    return new THREE.Quaternion(normalized.x, normalized.y, normalized.z, normalized.w)
  }
}

RE.registerComponent(ObjectSpinner);
        