import type { Dimension } from '@/common/interfaces'
import { BlurFilter, Container, Graphics, Point, Text, TextStyle } from 'pixi.js'
import { gsap } from 'gsap'
import { SoundManager } from '@/game/utilities/SoundManager'

export class Button extends Container {
  private dimension: Dimension
  private isDisabled: boolean = false
  private soundManager: SoundManager = new SoundManager()

  public disabledColor: number = 0xffff00
  public activeColor: number = 0xffff00
  public hoverColor: number = 0xffff00
  public shadowColor: number = 0x121212
  public clickSound: string = 'snd-click-btn'
  public textStyle: any = {
    fontFamily: 'Arial',
    fontSize: 15,
    fontWeight: 'bolder',
    fill: 0x121212,
    align: 'center',
  }

  constructor(
    protected text: string,
    protected point: Point,
    dimension: Dimension,
    protected action: Function,
  ) {
    super()
    this.dimension = { ...{ width: 100, height: 30 }, ...dimension }
    this.render()
  }

  protected getTextString() {
    return this.text
  }

  protected executeAction() {
    this.action()
  }

  set disabled(value: boolean) {
    this.isDisabled = value
    this.off('pointerdown')
    this.off('pointerover')
    this.off('pointerout')
    this.render()
  }

  get disabled() {
    return this.isDisabled
  }

  protected getTextObject(): Text {
    const { x, y } = this.point
    const { width = 0, height = 0 } = this.dimension
    const text = new Text({
      text: this.getTextString(),
      style: this.textStyle,
    })
    text.anchor = 0.5

    text.y = 2 + y + height / 2
    text.x = 2 + x + width / 2
    return text
  }

  protected getButtonBack() {
    const { x, y } = this.point
    const { width = 0, height = 0 } = this.dimension
    const color = this.isDisabled ? this.disabledColor : this.activeColor
    const back = new Graphics().roundRect(x, y, width + 4, height + 4, 5).fill(color)
    const shadow = new Graphics()
      .roundRect(x + 3, y + 2, width + 4, height + 4, 5)
      .fill(this.shadowColor)
    back.alpha = 0.7
    shadow.alpha = 1
    shadow.filters = [new BlurFilter({ strength: 15 })]
    this.addChild(shadow)
    this.addChild(back)
    return back
  }

  render() {
    this.removeChildren()
    const back = this.getButtonBack()
    const text = this.getTextObject()
    this.addChild(text)

    if (!this.isDisabled) {
      back.fill(this.activeColor)
      back.alpha = 0.7
      this.eventMode = 'static'
      this.cursor = 'pointer'
      this.on('pointerdown', (event) => {
        this.emit('click', event)
        this.onPointerDown(text, back)
      })
      this.on('pointerover', () => {
        back.alpha = 1
      })

      this.on('pointerout', () => {
        back.alpha = 0.7
      })
    } else {
      text.alpha = 0.7
      back.alpha = 0.5
      this.eventMode = 'none'
      this.cursor = 'default'
    }
  }

  private onPointerDown(text: Text, back: Graphics) {
    this.soundManager.play(this.clickSound)
    gsap
      .timeline()
      .to(
        [back, text],
        {
          duration: 0.06,
          x: '+=1',
          y: '+=2',
          ease: 'linear',
        },
        0,
      )
      .to([back, text], { duration: 0.06, x: '-=1', y: '-=2', ease: 'linear' })
    this.executeAction()
  }
}
