import assets from '../../../Assets/Sprites/**/*.yaml'
import { Shape, Sprite, SpritePart } from '../data/sprite'
import * as PIXI from 'pixi.js'

export const sprites: Record<string, Sprite> = {}

for (let [key, value] of Object.entries(assets)) {
  sprites[key] = new Sprite(value)
}

export class SpriteInstance {
  container: PIXI.Container
  sprite: Sprite|null = null
  spriteKey: string = ''
  animation?: SpritePart
  animationKey: string = ''
  set?: SpritePart
  setKey: string = ''
  subset?: SpritePart
  subsetKey: string = ''
  frame?: SpritePart
  frameIndex: number = 0
  frameCount: number = 0
  animate: boolean = true
  loop: boolean = true
  elapsed: number = 0

  constructor(ctor: string) {
    this.container = new PIXI.Container()
    this.setCtor(ctor)
  }

  setCtor(ctor: string) {
    this.container.removeChildren()
    let [spriteKey, animationKey, setKey, subsetKey, frameKey] = ctor.split('.')
    this.spriteKey = spriteKey
    this.animationKey = animationKey
    this.setKey = setKey
    this.subsetKey = subsetKey
    this.frameIndex = Number(frameKey)
    this.frameCount = 0
    this.sprite = sprites[spriteKey]
    if (!this.sprite) {
      this.container.addChild(new PIXI.Text('missing sprite'))
      return
    }
    this.animation = this.sprite.root.children[animationKey]
    this.set = this.animation.children[setKey]
    this.subset = this.set.children[subsetKey]
    //
    if (this.subset.frames) {
      if (this.frameIndex >= this.subset.frames.length) {
        this.frameIndex = 0
      }
      this.frameCount = this.subset.frames.length
      this.frame = this.subset.frames[this.frameIndex]
      let s = new PIXI.Sprite(this.frame.texture)
      if (this.frame.originX !== undefined) {
        s.pivot.x = this.frame.originX
      } else {
        s.pivot.x = s.width / 2
      }
      if (this.frame.originY !== undefined) {
        s.pivot.y = this.frame.originY
      } else {
        s.pivot.y = s.height / 2
      }
      this.container.addChild(s)
    }
  }

  update(delta: number) {
    if (!this.animate) return
    this.elapsed += delta
    while (this.frameCount > 0 && this.frame && this.elapsed >= this.frame.time && this.frame.time > 0) {
      this.elapsed -= this.frame.time
      this.frameIndex++
      if (this.frameIndex >= this.frameCount) {
        if (!this.loop) return
        this.frameIndex = 0
      }
      this.setCtor(`${this.spriteKey}.${this.animationKey}.${this.setKey}.${this.subsetKey}.${this.frameIndex}`)
    }
  }

  getBodyShape(): Shape|undefined {
    if (this.frame && this.frame.shapes) {
      return this.frame.shapes.find(v=>v.key==='body')
    }
    return
  }

  get width(): number {
    return this.frame?.width ?? this.container.width
  }
  get height(): number {
    return this.frame?.height ?? this.container.height
  }
  get originY(): number {
    return this.frame?.originY ?? 0
  }
  get originX(): number {
    return this.frame?.originX ?? 0
  }
}