import { Entity, ComponentConstructor, Component, World } from "ecsy"
import { Loader, interaction, Container } from "pixi.js"
import { Human } from "./Components/human"
import { Name } from "./Components/name"
import { Appearance } from "./Components/appearance"
import { InCabin } from "./Components/inCabin"
import { OrderZ } from "./Components/rendering/orderZ"
import { WalkRandomly } from "./Components/walkRandomly"
import { Position } from "./Components/position"
import { roomBounds, FirstNames, LastNames } from "./constants"
import { Clickable } from "./Components/clickable"
import globals from "./globals"

export let hide = "hide"
export let show = "show"

export function addOrSetComponent(
  entity: Entity,
  Component: ComponentConstructor<Component>,
  values: any
) {
  if (entity.hasComponent(Component)) {
    //component exists, copy values into it
    let component: any = entity.getMutableComponent(Component)
    if (component.copy) {
      component.copy(values)
    } else {
      for (let name in values) {
        component[name] = values[name]
      }
    }
  } else {
    //component doesn't exist, add new one
    entity.addComponent(Component, values)
  }
}

export function randomArrayValue(array: any[]): any {
  let randomIndex = Math.floor(Math.random() * array.length)
  return array[randomIndex]
}

export function setVisible(container: PIXI.Container, visible: boolean) {
  container.visible = visible
  emitRecursiveEvent(container, visible ? show : hide)
}

function emitRecursiveEvent(
  container: Container | PIXI.DisplayObject,
  event: string
) {
  container.emit(event)
  if (container instanceof Container)
    for (const child of container.children) {
      emitRecursiveEvent(child, event)
    }
}

export function createRandomHuman(world: World) {
  let resources = Loader.shared.resources
  let entity = world.createEntity()
  entity
    .addComponent(Human)
    .addComponent(Name, <Name>{
      first: randomArrayValue(FirstNames),
      last: randomArrayValue(LastNames),
    })
    .addComponent(Appearance, <Appearance>{
      idleTexture: resources["Human"].texture,
    }) //Todo: generate appearance from body traits instead?
    .addComponent(InCabin)
    .addComponent(Position, <Position>{ value: roomBounds.randomPoint() })
    .addComponent(OrderZ)
    .addComponent(WalkRandomly)
    .addComponent(Clickable, {
      actions: {
        click: (event: interaction.InteractionEvent) => {
          globals.selected.set(entity)
        },
      },
    })
}
