import * as planck from 'planck'
import { Action } from "./Action"
import { Entity } from "./Entity"
import { PuddleEntity } from './PuddleEntity'
import { WorldContext } from './World'

export class PlayerEntity extends Entity {
  action?: Action
  puddleTimer: number = 0
  constructor(ctor: string) {
    super(ctor)
  }
  act(actions: Action[]) {
    this.action = actions.sort((a, b) => {
      if (a.priority < b.priority) {
        return 1
      }
      if (a.priority > b.priority) {
        return -1
      }
      return 0
    })[0]
  }
  update(delta: number, ctx: WorldContext) {
    super.update(delta)

    let waterZones = this.zones.filter(v=>v.type==='fluid')
    if (waterZones.length) {
      this.puddleTimer += delta
      if (this.puddleTimer >= 600) {
        if (ctx) {
          let p = this.position
          p[0] += (this.sprite.frame?.originX??0) + ((this.sprite.frame?.width??0)/2??0)
          p[1] += (this.sprite.frame?.originY??0) + ((this.sprite.frame?.height??0)/2??0)
          ctx.addEntity(new PuddleEntity('effects.water.ripple.small.0'), 'ground', p[0], p[1])
        }
        this.puddleTimer = 0
      }
    }
    let shouldMove = false
    if (this.action) {
      // FIXME: Use physics.
      switch(this.action.type) {
        case 'west':
          if (this.direction !== 0) {
            if (this.direction < 180) {
              this.direction -= this.turnRate
            } else {
              this.direction += this.turnRate
            }
          }
          shouldMove = true
          break
        case 'east':
          if (this.direction !== 180) {
            if (this.direction < 180) {
              this.direction += this.turnRate
            } else {
              this.direction -= this.turnRate
            }
          }
          shouldMove = true
          break
        case 'north':
          if (this.direction !== 90) {
            if (this.direction < 90 || this.direction > 270) {
              this.direction += this.turnRate
            } else {
              this.direction -= this.turnRate
            }
          }
          shouldMove = true
          break
        case 'south':
          if (this.direction !== 270) {
            if (this.direction > 90 && this.direction < 270) {
              this.direction += this.turnRate
            } else {
              this.direction -= this.turnRate
            }
          }
          shouldMove = true
          break
      }
      if (this.direction > 360) {
        this.direction = 0
      } else if (this.direction < 0) {
        this.direction = 360
      }
    }

    if (shouldMove) {
      let r = this.direction * (Math.PI/180)
      if (Math.abs(this.velocity[0]) < this.maxSpeed) {
        this.velocity[0] -= Math.cos(r) * this.acceleration
      }
      if (Math.abs(this.velocity[1]) < this.maxSpeed) {
        this.velocity[1] -= Math.sin(r) * this.acceleration
      }
      let cardinal = this.getCardinal()
      this.sprite.setKey = 'run'
      if (this.sprite.subsetKey !== cardinal || this.sprite.subsetKey !== 'run') {
        this.sprite.setCtor(`${this.sprite.spriteKey}.${this.sprite.animationKey}.${this.sprite.setKey}.${cardinal}.${this.sprite.frameIndex}`)
      }
      this.sprite.animate = true
    } else {
      this.sprite.animate = false
      this.sprite.setKey = 'stand'
      this.sprite.setCtor(`${this.sprite.spriteKey}.${this.sprite.animationKey}.${this.sprite.setKey}.${this.getCardinal()}.0`)
    }

    //
    this.velocity[0] *= 0.7
    this.velocity[1] *= 0.7

    // Eh... let's manually handle velocity
    this.body?.setLinearVelocity(planck.Vec2(this.velocity[0], this.velocity[1]))
  }
  getCardinal(): string {
    const degreesPerDirection = 360 / 4
    const angle = this.direction + degreesPerDirection / 2

    if (angle >= 0 * degreesPerDirection && angle < 1 * degreesPerDirection) {
      return 'west'
    } else if (angle >= 1 * degreesPerDirection && angle < 2 * degreesPerDirection) {
      return 'north'
    } else if (angle >= 2 * degreesPerDirection && angle < 3 * degreesPerDirection) {
      return 'east'
    }
    return 'south'
  }
}

export function isPlayerEntity(o: any): o is PlayerEntity {
  return o.act
}
