import { ChatSendAfterEvent, ItemUseOnBeforeEvent, Player, system, world } from "@minecraft/server";
import { Mindkeeper, StoreType } from "../mindKeeper";
import { vector3 } from "../utils/vectorUtils";
import { Maker } from "./maker";
import { Trigger } from "./trigger";

export class TriggerEvent {
  player: Player;
  trigger: Trigger;

  constructor(player: Player, trigger: Trigger) {
    this.player = player;
    this.trigger = trigger;
  }
}

export type TriggerEventHandler = (event: TriggerEvent) => void;

export class Manager {
  private triggers: Trigger[] = [];
  private functionTriggers: Map<string, TriggerEventHandler> = new Map();
  private mindKeeper: Mindkeeper;
  private maker: Maker;

  constructor(mindKeeper: Mindkeeper) {
    this.mindKeeper = mindKeeper;
    this.maker = new Maker(mindKeeper, this);
  }

  RegisterStores() {
    this.mindKeeper.registerStore("triggers", StoreType.string);
    this.mindKeeper.registerStore("ShowTriggers", StoreType.boolean);
  }

  OnItemUse(event: ItemUseOnBeforeEvent) {
    this.maker.OnItemUse(event);
  }

  OnChat(event: ChatSendAfterEvent) {
    this.maker.OnChat(event);
  }
  //the func should have a TriggerEvent as a parameter
  RegisterFunctionTrigger(name: string, func: TriggerEventHandler) {
    this.functionTriggers.set(name, func);
  }

  //#region Loading / Saving

  Load() {
    this.LoadTriggers();
  }

  Save() {
    this.SaveTriggers();
  }

  private LoadTriggers() {
    const triggers = this.mindKeeper.get("triggers") as string;
    if (triggers === undefined) return;

    const data = JSON.parse(triggers);
    data.forEach((trigger: any) => {
      let point1 = vector3(trigger.point1.x, trigger.point1.y, trigger.point1.z);
      let point2 = vector3(trigger.point2.x, trigger.point2.y, trigger.point2.z);
      let eventToDispatch = trigger.eventToDispatch;

      let newTrigger = new Trigger(point1, point2);
      newTrigger.eventToDispatch = eventToDispatch;

      this.triggers.push(newTrigger);
    });
  }

  private SaveTriggers() {
    this.mindKeeper.set("triggers", JSON.stringify(this.triggers));
  }

  //#endregion

  AddTrigger(trigger: Trigger) {
    this.triggers.push(trigger);
  }

  GetCurrentActiveTriggers(): Trigger[] {
    return this.triggers.filter((trigger) => trigger.IsAnyPlayerInside());
  }

  Update() {
    const players = world.getAllPlayers();

    this.maker.Update();
    this.triggers.forEach((trigger: Trigger) => {
      trigger.Update();

      players.forEach((player) => {
        // player.sendMessage(`Player ${player.name} is in trigger ${trigger.IsPlayerInside(player)}`);
        if (trigger.hasPlayerEnterdTrigger(player)) {
          world.sendMessage(`Player ${player.name} entered trigger`);
          //Check if a function trigger is set
          const isFunctionSet = this.functionTriggers.has(trigger.eventToDispatch);

          if (isFunctionSet) {
            const event = new TriggerEvent(player, trigger);

            this.functionTriggers.get(trigger.eventToDispatch)!(event);
          } else {
            world.sendMessage(`Triggered ${trigger.eventToDispatch}`);
          }
        }
      });
    });
  }

  GetTriggers(): Trigger[] {
    return this.triggers;
  }
}
