import { Sprite, Texture, Ticker } from 'pixi.js'

export abstract class SpriteBase {
  private _interactive: boolean = false
  protected sprite: Sprite = new Sprite()

  constructor(
    protected ticker?: Ticker,
    protected scale: number = 1
  ) {
    this.ticker = ticker
    this.scale = scale
  }

  abstract createTexture(): Texture

  set interactive(value: boolean) {
    this._interactive = value
    this.sprite.eventMode = value ? 'static' : 'none'
    this.sprite.cursor = value ? 'pointer' : 'default'
  }

  get interactive(): boolean {
    return this._interactive
  }

  get x(): number {
    return this.sprite.x
  }

  get y(): number {
    return this.sprite.y
  }

  get width(): number {
    return this.sprite.width
  }

  get height(): number {
    return this.sprite.height
  }

  set alpha(value: number) {
    this.sprite.alpha = value
  }

  get alpha(): number {
    return this.sprite.alpha
  }

  set anchor(value: { x: number; y: number } | number) {
    if (typeof value === 'number') {
      this.sprite.anchor.set(value)
      return
    }
    this.sprite.anchor.set(value.x, value.y)
  }

  on(event: string, fn: any): void {
    this.sprite.on(event, fn)
  }

  off(event: string): void {
    this.sprite.off(event)
  }

  getSprite(): Sprite {
    return this.sprite
  }

  setPosition(x: number, y: number) {
    this.sprite.x = x
    this.sprite.y = y
  }

  setFilters(filters: any[]) {
    this.sprite.filters = filters
  }

  clearFilters() {
    this.sprite.filters = []
  }

  animateTo(x: number, y: number) {
    const initialX = this.sprite.x
    const initialY = this.sprite.y

    const deltaX = x - this.sprite.x
    const deltaY = y - this.sprite.y
    let elapsed: number = 0
    const duration: number = 10

    const tick: any = (delta: any) => {
      elapsed += delta.deltaTime
      const progress = Math.min(elapsed / duration, 1)

      this.sprite.x = initialX + deltaX * progress
      this.sprite.y = initialY + deltaY * progress

      if (progress === 1) {
        this.ticker?.remove(tick)
      }
    }

    this.ticker?.add(tick)
  }

  addTo(container: any) {
    container.addChild(this.sprite)
  }
}
