import { Player, RawMessage, world } from "@minecraft/server";
import { ActionFormData, MessageFormData } from "@minecraft/server-ui";
import { getModId } from "lazuli-core";
import { setEquipmentItem } from "lazuli-utils";

/**
 * A list of registried jobs id.
 */
export const ReistriedJobIdList: string[] = [];
/**
 * A list of registried jobs.
 */
export const ReistriedJobList: Job[] = [];

export class Job {
  constructor(
    /**
     * Id of the job.
     */
    public readonly id: string,
    public effect: JobEffect,
    public asset: JobAsset
  ) {
    this.register();
  }
  protected register() {
    ReistriedJobIdList.push(this.id);
    ReistriedJobList.push(this);
  }
  displayInfo(player: Player, board?: JobBoard) {
    const infoForm = new MessageFormData()
      .title(this.asset.name)
      .body(generateJobBody(this, player))
      .button1({ translate: "gui.ok" })
      .button2({ translate: "job.tryUpdate" });
    infoForm.show(player).then((response) => {
      if (
        response.canceled ||
        response.selection === undefined ||
        response.selection === 0
      ) {
        board?.display(player);
      }
    });
  }
  giveJob(player: Player): void {
    player.setDynamicProperty(`${getModId}.job:${this.id}`, true);
    player.setDynamicProperty(`${getModId}.job_level:${this.id}`, 1);
  }
  hasJob(player: Player): boolean {
    if (player.getDynamicProperty(`${getModId}.job:${this.id}`)) {
      return true;
    } else {
      return false;
    }
  }
}

export class JobOffer {
  constructor(public readonly typeId: string, public job: Job) {
   this.register();
  }
  protected register() {
    world.afterEvents.itemUse.subscribe((event) => {
      if (this.typeId === event.itemStack.typeId) {
        setEquipmentItem(event.source);
        this.job.giveJob(event.source);
      }
    });
  }
}

export class JobBoard {
  constructor(public typeId: string) {
    this.register();
  }
  protected register() {
    world.afterEvents.itemUse.subscribe((event) => {
      if (this.typeId === event.itemStack.typeId) {
        this.display(event.source);
      }
    });
  }
  display(player: Player) {
    const form = new ActionFormData();
    const displayedJobs: Job[] = [];
    JobManager.getHasJobs(player).forEach((job) => {
      form.button(job.asset.name, job.asset.iconPath);
      displayedJobs.push(job);
    });
    form.show(player).then((response) => {
      if (response.selection) {
        displayedJobs[response.selection].displayInfo(player);
      }
    });
  }
}

export class JobManager {
  private constructor() {}
  static getRegistriedJobs(): Job[] {
    return ReistriedJobList;
  }
  static getRegistriedJobsId(): string[] {
    return ReistriedJobIdList;
  }
  static getHasJobs(player: Player): Job[] {
    const JobList: Job[] = [];
    this.getRegistriedJobs().forEach((job) => {
      if (job.hasJob(player)) {
        JobList.push(job);
      }
    });
    return JobList;
  }
}

// TODO
export function generateJobBody(job: Job, player: Player): RawMessage {
  const body: RawMessage = {
    rawtext: [
      typeof job.asset.description === "string"
        ? { text: job.asset.description }
        : job.asset.description,
    ],
  };
  return body;
}

// TODO
export interface JobEffect {}

export interface JobAsset {
  name: string | RawMessage;
  description: string | RawMessage;
  iconPath?: string;
}
