import { System, Entity, Not } from "ecsy"
import { PixiRepresentation } from "../Components/rendering/pixiRepresentation"
import { Clickable, InitializedClickable } from "../Components/clickable"
import globals from "../globals"
import { interaction } from "pixi.js"
import { HoverObject, InitializedHoverObject } from "../Components/hoverObject"
import { TooltipSystem } from "./UI/TooltipSystem"
import { hide } from "../util"

export class MouseSystem extends System {
  priority = 80

  init() {
    //the great deselector
    globals.app.stage.interactive = true
    globals.app.stage.on("click", (event: interaction.InteractionEvent) => {
      if (event.target == event.currentTarget) globals.selected.set(null)
    })
  }

  // This method will get called on every frame by default
  execute(delta: number) {
    // Iterate through all the entities on the query
    this.queries.newClickables.results.forEach((entity: Entity) => {
      let object = entity.getComponent(PixiRepresentation).value
      let clickable = entity.getComponent(Clickable)
      object.interactive = true
      for (let action in clickable.actions) {
        object.on(action, clickable.actions[action])
      }
      entity.addComponent(InitializedClickable)
    })

    this.queries.changedClickables.changed.forEach((entity: Entity) => {
      let object = entity.getComponent(PixiRepresentation).value
      let clickable = entity.getComponent(Clickable)
      object.removeAllListeners()
      for (let action in clickable.actions) {
        object.on(action, clickable.actions[action])
      }
    })

    this.queries.invisibleClickables.results.forEach((entity: Entity) => {
      //remove init clickable tag so it gets initialized again as soon as a pixirepresentation exists again
      entity.removeComponent(InitializedClickable)
    })

    // Iterate through all the entities on the query
    this.queries.newHoverObjects.results.forEach((entity: Entity) => {
      let object = entity.getComponent(PixiRepresentation).value
      let hover = entity.getComponent(HoverObject)

      let ttSystem = globals.world.getSystem(TooltipSystem) as TooltipSystem

      object.interactive = true
      object.on("pointerover", () => ttSystem?.showTooltip(hover.label, entity))
      object.on("pointerout", () => ttSystem?.cancelTooltip(entity))
      object.on("pointercancel", () => ttSystem?.cancelTooltip(entity))
      object.on(hide, () => ttSystem?.cancelTooltip(entity))

      entity.addComponent(InitializedHoverObject)
    })

    this.queries.changedHoverObjects.changed.forEach((entity: Entity) => {
      let object = entity.getComponent(PixiRepresentation).value
      let hover = entity.getComponent(HoverObject)

      let ttSystem = globals.world.getSystem(TooltipSystem) as TooltipSystem
      object.removeListener("pointerover")
      object.removeListener("pointerout")
      object.removeListener("pointercancel")
      object.removeListener(hide)
      object.on("pointerover", () => ttSystem?.showTooltip(hover.label, entity))
      object.on("pointerout", () => ttSystem?.cancelTooltip(entity))
      object.on("pointercancel", () => ttSystem?.cancelTooltip(entity))
      object.on(hide, () => ttSystem?.cancelTooltip(entity))
    })

    this.queries.invisibleHoverObjects.results.forEach((entity: Entity) => {
      //remove init clickable tag so it gets initialized again as soon as a pixirepresentation exists again
      entity.removeComponent(InitializedHoverObject)
    })
  }

  static queries = {
    //clickable stuff
    newClickables: {
      components: [PixiRepresentation, Clickable, Not(InitializedClickable)],
    },
    changedClickables: {
      components: [PixiRepresentation, Clickable, InitializedClickable],
      listen: {
        changed: [Clickable],
      },
    },
    invisibleClickables: {
      components: [InitializedClickable, Not(PixiRepresentation)],
    },

    newHoverObjects: {
      components: [
        PixiRepresentation,
        HoverObject,
        Not(InitializedHoverObject),
      ],
    },
    changedHoverObjects: {
      components: [PixiRepresentation, HoverObject, InitializedHoverObject],
      listen: {
        changed: [Clickable],
      },
    },
    invisibleHoverObjects: {
      components: [InitializedHoverObject, Not(PixiRepresentation)],
    },
  }
  queries: any
}
