// SPDX-FileCopyrightText: 2021 Johannes Loher
//
// SPDX-License-Identifier: MIT

import { DS4Item } from "../documents/item/item";
import { notifications } from "../ui/notifications";
import { getGame } from "../utils/utils";
import { getActiveActorAndToken } from "./helpers";

/**
 * Create a macro from an item drop.
 * Get an existing roll item macro if one exists, otherwise create a new one.
 * @param {object} data The item drop data
 * @param {string} slot The hotbar slot to use
 * @returns {Promise<void>} A promise that resolves once the macro has been created.
 */
export async function createRollItemMacro(data, slot) {
  const item = await Item.implementation.fromDropData(data);
  if (!item.parent) {
    return notifications.warn(getGame().i18n.localize("DS4.WarningMacrosCanOnlyBeCreatedForOwnedItems"));
  }
  if (!DS4Item.rollableItemTypes.includes(item.type)) {
    return notifications.warn(
      getGame().i18n.format("DS4.WarningItemIsNotRollable", {
        name: item.name,
        id: item.id,
        type: item.type,
      }),
    );
  }

  const macro = await getOrCreateRollItemMacro(item);
  await getGame().user?.assignHotbarMacro(macro ?? null, slot);
}

/**
 * @param {object} item The item
 * @returns {Promise<Macro | undefined>} A promise that resolves to the created macro
 */
async function getOrCreateRollItemMacro(item) {
  const command = `game.ds4.macros.rollItem("${item.id}");`;

  const existingMacro = getGame().macros?.find((m) => m.name === item.name && m.command === command);
  if (existingMacro) {
    return existingMacro;
  }

  return Macro.create(
    {
      command,
      name: item.name,
      type: "script",
      img: item.img,
      flags: { "ds4.itemMacro": true },
    },
    { renderSheet: false },
  );
}

/**
 * Executes the roll item macro for the item associated to the given `itemId`.
 * @param {string} itemId   The id of the item to roll
 * @returns {Promise<void>} A promise that resolves once the item has been rolled.
 */
export async function rollItem(itemId) {
  const { actor, token } = getActiveActorAndToken();
  if (!actor) {
    return notifications.warn(getGame().i18n.localize("DS4.WarningMustControlActorToUseRollItemMacro"));
  }

  const item = actor.items.get(itemId);
  if (!item) {
    return notifications.warn(
      getGame().i18n.format("DS4.WarningControlledActorDoesNotHaveItem", {
        actorName: actor.name,
        actorId: actor.id,
        itemId,
      }),
    );
  }

  return item.roll({ speaker: { token } }).catch((e) => notifications.error(e, { log: true }));
}
