import * as RE from 'rogue-engine'
import * as THREE from 'three'
import { TweenManager } from './Library/SimpleTweens'
import TileRaycastReceiver from './TileRaycastReceiver.re'
import Easing from './Library/Easings'
import AsyncLoader from './Library/AsyncLoader';
import Pathway from './Pathway.re'

export default class CombatLogic extends RE.Component {

  @RE.Prop("Object3D") playGrid
  @RE.Prop("Prefab") tile

  @RE.Prop("Material") hoverMaterial
  @RE.PropList("Material") tileMaterials = []

  @RE.Prop("Vector2") boardDimensions = new THREE.Vector2(8, 8)
  @RE.Prop("Number") maxColors = 5

  tweenManager = new TweenManager()
  loader = new AsyncLoader()
  selectedTiles = []
  movesRemaining = 8
  score = 0

  awake() {
    this.tweenManager.awake()
  }

  start() {
    // let level = GameData.get("active-level") ?? 1
    // this.levelData = GameData.get("level-data")[level] ?? {x: this.boardDimensions.x, y: this.boardDimensions.y, c: this.maxColors}

    // this.score = this.levelData.g
    // this.movesRemaining = 3

    for(let child of this.playGrid.children) {
      this.playGrid.remove(child) 
    }

    // this.loader.loadStaticText("gamehud.html").then(html => {
    //   RE.Runtime.uiContainer.innerHTML = html
      for(let i = 0; i < this.boardDimensions.x*this.boardDimensions.y; i++) {
        this.instantiateTile(
          new THREE.Vector2((i % this.boardDimensions.x), Math.floor(i / this.boardDimensions.x)),
          Math.floor(1500 * Math.random()) + 1800,
        )
      }

    //   this.movesDisplay = document.getElementById("moves")
    //   this.scoreDisplay = document.getElementById("score")
    // })
    
    this.tweenManager.start()
  }

  instantiateTile(gridPosition, delay, startingY = 14, easingFunction = Easing.Elastic.EaseOut) {
    let tile = this.tile.instantiate(this.playGrid)
    let component = RE.getComponent(TileRaycastReceiver, tile)
    component.initialize(
      gridPosition,
      this.boardDimensions,
      this.tileMaterials[Math.floor(Math.random() * Math.min(this.maxColors, this.tileMaterials.length))],
      this.hoverMaterial,
      this.tweenManager,
      delay,
      startingY,
      easingFunction,
      )
  }

  update() {
    this.tweenManager.update()

    if(RE.Input.mouse.getButtonUp(0) || RE.Input.touch.endTouches.length > 0) {
      let pathway = RE.getComponent(Pathway, this.playGrid)
      if (pathway) {
        pathway.clearPoints()
      }
      if(this.selectedTiles.length == 1) {
        this.selectedTiles.length = 0
      }

      if(this.selectedTiles.length > 1 && this.selectedTiles.length < 5) {
        this.movesRemaining--
      }
      if(this.selectedTiles.length >= 5) {
        this.movesRemaining += Math.floor((this.selectedTiles.length - 5) / 3)
      }
      // this.movesDisplay.innerHTML = this.movesRemaining

      let moveScore = (this.selectedTiles.length * 10)
      this.selectedTiles.forEach(tileComponent => {
        moveScore *= Math.max(1, Math.floor(this.selectedTiles.indexOf(tileComponent) / 5))
        tileComponent.remove(this.tweenManager)
        this.instantiateTile(
          tileComponent.object3d.gridPosition,
          Math.floor(1500 * Math.random()) + 300,
          14,
          Easing.Exponential.EaseOut,
        )
        
      })
      this.selectedTiles.length = 0
      this.score += moveScore
      // this.scoreDisplay.innerHTML = this.score
    }

    if(RE.Input.keyboard.getKeyUp("Escape")) {
      RE.App.loadScene("Main Menu")
    }

    if(this.movesRemaining == 0) {
      //GameData.set('final-score', 1337)
      RE.App.loadScene("World Map")
    }
  }

  // buildLine() {
  //   let positions = []
  //   this.selectedTiles.forEach(tileComponent => {
  //     let position = tileComponent.getPosition()
  //     positions.push(new THREE.Vector3(position.x, 1.2, position.y))
  //   })

  //   this.lineGeometry = new LineGeometry()
  //   this.lineMaterial = new LineMaterial({
  //     color: 0xffffff,
  //     linewidth: 5, // in pixels
  //     vertexColors: true,
  //     //resolution:  // to be set by renderer, eventually
  //     dashed: false
  //   });

  //   this.line = new Line2(this.lineGeometry, this.lineMaterial);
  //   this.line.computeLineDistances();
  //   this.line.scale.set(1, 1, 1);
  // }

  addTile(tileComponent) {
    let isAdded = false
    if(this.isStepBack(tileComponent)) {
      this.selectedTiles.pop(tileComponent)
    } else if(this.isValidTileToSelect(tileComponent)) {
      this.selectedTiles.push(tileComponent)
      isAdded = true
    }

    let pathway = RE.getComponent(Pathway, this.playGrid)
    if (pathway) {
      pathway.recomputePath(this.selectedTiles)
    }
    return [isAdded, this.selectedTiles]
  }

  isValidTileToSelect(tileComponent) {
    if(this.selectedTiles.length == 0) {
      return true
    }
    let lastAddedTile = this.selectedTiles[this.selectedTiles.length - 1]
    let initialColor = lastAddedTile.getOriginalMaterial().name

    return this.selectedTiles.indexOf(tileComponent) == -1 &&
    tileComponent.getOriginalMaterial().name == initialColor &&
    this.isNearbyTile(lastAddedTile.object3d.gridPosition, tileComponent.object3d.gridPosition)
  }

  isNearbyTile(startingPosition, newPosition) {
    return (newPosition.x == startingPosition.x - 1 ||
    newPosition.x == startingPosition.x ||
    newPosition.x == startingPosition.x + 1) &&
    (newPosition.y == startingPosition.y - 1 ||
      newPosition.y == startingPosition.y ||
      newPosition.y == startingPosition.y + 1)
  }

  isStepBack(tileComponent) {
    return this.selectedTiles.length > 1 && this.selectedTiles.indexOf(tileComponent) == this.selectedTiles.length - 2
  }
}

RE.registerComponent(CombatLogic);
