import * as PIXI from 'pixi.js'

export class Shape {
  key: string
  sensor: boolean
  constructor(o: any) {
    this.key = o.key
    this.sensor = o.sensor
  }
}

export class ShapeCircle extends Shape {
  radius: number = 8
  x: number = 0
  y: number = 0
  constructor(o: any) {
    super(o)
    this.radius = o.circle.radius
    this.x = o.circle.x
    this.y = o.circle.y
  }
}

export class ShapePoints extends Shape {
  points: [number, number][]
  constructor(o: any) {
    super(o)
    this.points = o.points
  }
}

export class Sprite {
  uuid: string
  texture: PIXI.Texture
  originX: number = 0
  originY: number = 0
  x: number = 0
  y: number = 0
  width: number = 0
  height: number = 0
  root: SpritePart

  constructor(o: any) {
    this.uuid = o.uuid
    this.texture = PIXI.Texture.from('./Assets/Sprites/'+o.source)
    this.texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST
    this.root = new SpritePart(o, {
      texture: this.texture,
      originX: 0,
      originY: 0,
      x: 0,
      y: 0,
      width: 0,
      height: 0,
      time: 0,
      source: '',
    }, this.texture)
  }
}

export interface SpritePartI {
  texture: PIXI.Texture
  originX: number
  originY: number
  x: number
  y: number
  width: number
  height: number
  time: number
  source: string
  children?: Record<string, SpritePart>
  shapes?: (ShapeCircle|ShapePoints)[]
}

export class SpritePart {
  texture: PIXI.Texture
  originX: number = 0
  originY: number = 0
  x: number = 0
  y: number = 0
  width: number = 0
  height: number = 0
  time: number = 0
  source: string = ''
  children: Record<string, SpritePart> = {}
  frames?: SpritePart[]
  shapes: (ShapeCircle|ShapePoints)[] = []

  constructor(o: any, p: SpritePartI, t: PIXI.Texture) {
    this.time = o.time ?? p.time
    this.x = o.x ?? p.x
    this.y = o.y ?? p.y
    this.width = o.width ?? p.width
    this.height = o.height ?? p.height
    this.originX = o.origin_x ?? p.originX
    this.originY = o.origin_y ?? p.originY
    if (o.source) {
      t = PIXI.Texture.from('./Assets/Sprites/'+o.source)
      t.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST
    }
    if (this.x === p.x && this.y === p.y && this.width === p.width && this.height === p.height && o.source === p.source) {
      this.texture = p.texture
    } else {
      this.texture = new PIXI.Texture(t.baseTexture, new PIXI.Rectangle(this.x, this.y, this.width, this.height))
    }

    if (o.animations) {
      for (let [key, value] of Object.entries(o.animations)) {
        this.children[key] = new SpritePart(value, this, t)
      }
    } else if (o.sets) {
      for (let [key, value] of Object.entries(o.sets)) {
        this.children[key] = new SpritePart(value, this, t)
      }
    } else if (o.subsets) {
      for (let [key, value] of Object.entries(o.subsets)) {
        this.children[key] = new SpritePart(value, this, t)
      }
    } else if (o.frames) {
      this.frames = o.frames.map((v: any) => {
        return new SpritePart(v, this, t)
      })
    }

    if (o.shapes) {
      for (let s of o.shapes) {
        if (s.circle) {
          this.shapes.push(new ShapeCircle(s))
        } else {
          this.shapes.push(new ShapePoints(s))
        }
      }
    }
  }
}