import { TimeOfDay, system, world, ItemStack, StructureAnimationMode, StructureRotation, StructureSaveMode } from "@minecraft/server";
import { getStringAfter, checkBelowEntityDespawn, getStringBefore, checkLocation, getEntityRotation, getLocationbyFacingBlock, stringBetween, getGamemode, getElementPosition, getElementPositionArrayWithObjects } from "./helpers";
import { cameraCutscene } from "../events/camera";
import { ActionFormData } from "@minecraft/server-ui";

const foodItems = [
  "minecraft:apple",
  "minecraft:golden_apple",
  "minecraft:enchanted_golden_apple",
  "minecraft:bread",
  "minecraft:carrot",
  "minecraft:egg",
  "minecraft:golden_carrot",
  "minecraft:potato",
  "minecraft:baked_potato",
  "minecraft:poisonous_potato",
  "minecraft:beetroot",
  "minecraft:beetroot_soup",
  "minecraft:mushroom_stew",
  "minecraft:rabbit_stew",
  "minecraft:suspicious_stew",
  "minecraft:melon_slice",
  "minecraft:glistering_melon_slice",
  "minecraft:pumpkin_pie",
  "minecraft:cookie",
  "minecraft:cake",
  "minecraft:sweet_berries",
  "minecraft:honey_bottle",
  "minecraft:porkchop",
  "minecraft:cooked_porkchop",
  "minecraft:beef",
  "minecraft:cooked_beef",
  "minecraft:chicken",
  "minecraft:cooked_chicken",
  "minecraft:mutton",
  "minecraft:cooked_mutton",
  "minecraft:cod",
  "minecraft:cooked_cod",
  "minecraft:salmon",
  "minecraft:cooked_salmon",
  "minecraft:tropical_fish",
  "minecraft:pufferfish",
  "minecraft:spider_eye",
  "minecraft:rotten_flesh",
  "minecraft:rabbit",
  "minecraft:cooked_rabbit",
  "minecraft:sugar",
  "minecraft:sugar_cane",
];

const recipes = [
  { input1: "minecraft:sweet_berries", input2: "minecraft:sweet_berries", output: "hb_cb:sweet_berry_soup" },
  { input1: "minecraft:carrot", input2: "minecraft:carrot", output: "hb_cb:carrot_soup" },
  { input1: "minecraft:pumpkin", input2: "minecraft:pumpkin_seeds", output: "hb_cb:pumpkin_soup" },
  { input1: "minecraft:potato", input2: "minecraft:potato", output: "hb_cb:potato_soup" },
  { input1: "minecraft:rotten_flesh", input2: "minecraft:rotten_flesh", output: "hb_cb:rotten_stew" },
  { input1: "minecraft:glow_berries", input2: "minecraft:glow_berries", output: "hb_cb:glow_berry_soup" },
  { input1: "minecraft:tropical_fish", input2: "minecraft:pufferfish", output: "hb_cb:tropical_stew" },
  { input1: "minecraft:crimson_fungus", input2: "minecraft:warped_fungus", output: "hb_cb:nether_stew" },
  { input1: "minecraft:beef", input2: "minecraft:carrot", output: "hb_cb:beef_stew" },
  { input1: "minecraft:enchanted_golden_apple", input2: "minecraft:golden_carrot", output: "hb_cb:golden_stew" },
];

export class kettleHandler {
  static initialized = false;
  constructor() {
    this.initialize();
  }

  initialize() {
    if (!kettleHandler.initialized) {
      kettleHandler.initialized = true;
      this.processSubscriptions();
    } else {
    }
  }
  processSubscriptions() {
    let curTick = 0;
    const INIT_TIME = 0;

    system.runInterval(() => {
      try {
        if (curTick > INIT_TIME) {
          const allPlayers = world.getAllPlayers();
          allPlayers.forEach((player) => {
            if (!player.isValid()) return;
            else {
              checkBelowEntityDespawn(player, "kettle");
            }
          });
        }
        curTick++;
      } catch (e) {
        console.warn(e);
      }
    }, 10);

    world.afterEvents.playerInteractWithEntity.subscribe((event) => {
      const player = event.player;
      const typeId = player.typeId;
      if (typeId !== "minecraft:player") {
        return;
      }
      if (event.target.typeId.includes("hb_cb:") && event.target.typeId.includes("kettle")) {
        const kettle = event.target;
        this.addInputItem(player, kettle);
      } else return;
    });
    world.afterEvents.itemUse.subscribe((event) => {
      const player = event.source;
      const typeId = player.typeId;
      if (typeId !== "minecraft:player") {
        return;
      }
      const holdingItem = player.getComponent("equippable").getEquipment("Mainhand");
      if (holdingItem == undefined) {
        return;
      }
      if (holdingItem.typeId.includes("hb_cb:") && holdingItem.typeId.includes("kettle")) this.spawnKettle(player, holdingItem);
    });
    system.afterEvents.scriptEventReceive.subscribe((event) => {
      if (event.sourceEntity == undefined) return;
      else {
        if (event.sourceEntity.typeId.includes("hb_cb:") && event.sourceEntity.typeId.includes("kettle")) {
          let kettle = event.sourceEntity;
          switch (event.id) {
            case "hb_cb:despawn_tick_hit_trigger":
              if (kettle.getProperty("hb_cb:despawn_tick") < 4) {
                kettle.runCommand("/playsound block.lantern.break @a[r=10] ~~~ 1 1");
                kettle.runCommand("/playanimation @s animation.hb_cb.kettle.break");
                kettle.runCommand("/event entity @s hb_cb:despawn_tick_hit");
              }
              break;
            case "hb_cb:kettle_despawn":
              this.despawnKettle(kettle);
              break;
            default:
              break;
          }
        }
      }
    });
  }

  addInputItem(player, kettle) {
    //////////world.sendMessage("interact!");
    //////////world.sendMessage("current items: " + kettle.getProperty("hb_cb:items_inside_bowl").toString());
    const item = player.getComponent("equippable").getEquipment("Mainhand");
    if (item == undefined) {
      return;
    }
    switch (kettle.getProperty("hb_cb:items_inside_bowl")) {
      case 0:
        if (this.isHeldItemAnInput(item.typeId)) {
          //////////world.sendMessage("The held item is a recipe input!");
          kettle.setDynamicProperty("hb_cb:input1", item.typeId);
          //////////world.sendMessage(item.typeId + " put in!");
          player.runCommand("/clear @s " + item.typeId + " 0 1");
          //////////world.sendMessage("0 items put in");
          //////////world.sendMessage("put in first item");
          kettle.setProperty("hb_cb:items_inside_bowl", 1);
          kettle.playAnimation("add_item");
          player.runCommand("/playsound hb_cb:kettle_place_food @a[r=10] ~~~ 1 1");

          return;
        } else {
          //////////world.sendMessage("The held item is not a recipe item.");
          return;
        }

      case 1:
        if (this.isHeldItemAnInput(item.typeId)) {
          //////////world.sendMessage("The held item is a recipe input!");
          kettle.setDynamicProperty("hb_cb:input2", item.typeId);
          //////////world.sendMessage(item.typeId + " put in!");
          player.runCommand("/clear @s " + item.typeId + " 0 1");
          kettle.setProperty("hb_cb:items_inside_bowl", 2);
          kettle.playAnimation("add_item");
          player.runCommand("/playsound hb_cb:kettle_place_food @a[r=10] ~~~ 1 1");

          //////////world.sendMessage("1 items put in");
          //////////world.sendMessage("put in second item");
          return;
        } else {
          //////////world.sendMessage("The held item is not a recipe item.");
          return;
        }

      case 2:
        if (item == undefined) {
          //////////world.sendMessage("use a bowl to interact");
          return;
        } else if (item.typeId == "minecraft:bowl") {
          let input1 = kettle.getDynamicProperty("hb_cb:input1");
          let input2 = kettle.getDynamicProperty("hb_cb:input2");
          let outputItem = this.getRecipeOutput(input1, input2);
          if (outputItem == null) {
            system.runTimeout(() => {
              // ////world.sendMessage("test");
              kettle.setProperty("hb_cb:items_inside_bowl", 0);
            }, 20);
            kettle.playAnimation("failure");
            player.runCommand("/playsound hb_cb:kettle_cooking_fail @a[r=10] ~~~ 1 1");
            return;
            // ////world.sendMessage("fail recipe");
          } else {
            kettle.playAnimation("success");
            player.runCommand("/playsound hb_cb:kettle_cooking_success @a[r=10] ~~~ 1 1");
            let spawnedItem = new ItemStack(outputItem);
            let kettleItem = world.getDimension(kettle.dimension.id).spawnItem(spawnedItem, { x: kettle.location.x, y: kettle.location.y + 1.2, z: kettle.location.z });
            kettleItem.clearVelocity();
            kettle.clearDynamicProperties();
            system.runTimeout(() => {
              // ////world.sendMessage("test");
              kettle.setProperty("hb_cb:items_inside_bowl", 0);
            }, 5);
            //////////world.sendMessage("2 items put in, now only interactable with bowl to get new item");
          }

          player.runCommand("/clear @s " + item.typeId + " 0 1");
          return;
        } else if (item.typeId.includes("hb_cb:ceramic_pot_item")) {
          let input1 = kettle.getDynamicProperty("hb_cb:input1");
          let input2 = kettle.getDynamicProperty("hb_cb:input2");
          let outputItem = this.getRecipeOutput(input1, input2);
          if (outputItem == null) {
            system.runTimeout(() => {
              // ////world.sendMessage("test");
              kettle.setProperty("hb_cb:items_inside_bowl", 0);
            }, 20);
            kettle.playAnimation("failure");
            player.runCommand("/playsound hb_cb:kettle_cooking_fail @a[r=10] ~~~ 1 1");
            // ////world.sendMessage("fail recipe");
          } else {
            kettle.playAnimation("success");
            player.runCommand("/playsound hb_cb:kettle_cooking_success_ceramic_pot @a[r=10] ~~~ 1 1");
            let spawnedItem = new ItemStack("hb_cb:ceramic_pot_item_filled");

            spawnedItem.setDynamicProperty("hb_cb:load_amount", 3);
            spawnedItem.setDynamicProperty("hb_cb:food_type", getStringAfter(":", outputItem));
            spawnedItem.setLore([
              "§r§2Contains: §r§o" +
                getStringAfter(":", outputItem)
                  .split("_")
                  .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
                  .join(" ") +
                " §r§a3/3",
            ]);
            let kettleItem = world.getDimension(kettle.dimension.id).spawnItem(spawnedItem, { x: kettle.location.x, y: kettle.location.y + 1.2, z: kettle.location.z });
            kettleItem.clearVelocity();
            kettle.clearDynamicProperties();
            system.runTimeout(() => {
              // ////world.sendMessage("test");
              kettle.setProperty("hb_cb:items_inside_bowl", 0);
            }, 5);
            //////////world.sendMessage("2 items put in, now only interactable with bowl to get new item");
          }

          player.runCommand("/clear @s " + item.typeId + " 0 1");
          return;
        } else {
          //////////world.sendMessage("use a bowl to interact");
        }

        break;

      default:
        break;
    }
    // }

    // if (kettle.getDynamicProperty("hb_cb:input1")) {
    // }
    // return;
  }

  handleItem(item, player) {
    if (!item) return; // Early exit if the item is undefined

    if (item.typeId == "hb_cb:kettle_item") {
      const cooldownComp = item.getComponent("cooldown");
      if (!cooldownComp) return;

      if (player.getItemCooldown(cooldownComp.cooldownCategory) > 0) return;

      if (player.isSneaking) {
        player.addEffect("absorption", 200, { amplifier: 0, showParticles: false });
        cooldownComp.startCooldown(player);
      }
    } else return;
  }

  spawnKettle(player, item) {
    const raycastBlock = player.getBlockFromViewDirection({ includeLiquidBlocks: false, includePassableBlocks: false, maxDistance: 8 });
    if (raycastBlock == undefined) return;
    else {
      let gamemodeCreative = getGamemode(player, 1);
      const location = raycastBlock.block.location;
      const face = raycastBlock.face;

      let placeLoc = getLocationbyFacingBlock(face, location);
      if (checkLocation(placeLoc, player, placeLoc, 0)) return;

      let yRotation = getEntityRotation(player);
      let orientation;
      switch (yRotation) {
        case 0:
          orientation = "north";
          break;
        case 90:
          orientation = "east";
          break;
        case 180:
          orientation = "south";
          break;
        case 270:
          orientation = "west";
          break;

        default:
          break;
      }

      let block = world.getDimension(player.dimension.id).getBlock({ x: placeLoc.x, y: placeLoc.y, z: placeLoc.z });
      let block2 = world.getDimension(player.dimension.id).getBlock({ x: placeLoc.x, y: placeLoc.y + 1, z: placeLoc.z });
      block.setType("hb_cb:kettle_block");
      block2.setType("hb_cb:kettle_block");

      // let kettle = world.getDimension(player.dimension.id).spawnEntity(item.typeId, placeLoc);

      // player.runCommand("/playsound block.lantern.place @a[r=10] ~~~ 1 1");
      player.runCommand("/summon " + getStringBefore(item.typeId, "_item") + " " + placeLoc.x.toString() + " " + placeLoc.y.toString() + " " + placeLoc.z.toString() + " " + yRotation.toString() + " 0");
      if (!gamemodeCreative) {
        player.runCommand("/clear @s " + item.typeId + " 0 1");
      }
    }
  }

  despawnKettle(kettle) {
    kettle.runCommand("/playanimation @s animation.hb_cb.kettle.despawn");
    system.waitTicks(1).then(() => {
      if (kettle.hasTag("hb_cb:start_block_despawn")) {
        kettle.teleport({ x: kettle.location.x, y: kettle.location.y + 0.5, z: kettle.location.z });
      }
      let block = world.getDimension(kettle.dimension.id).getBlock({ x: kettle.location.x, y: kettle.location.y, z: kettle.location.z });
      let block2 = world.getDimension(kettle.dimension.id).getBlock({ x: kettle.location.x, y: kettle.location.y + 1, z: kettle.location.z });
      block.setType("minecraft:air");
      block2.setType("minecraft:air");
      let spawnedItem = new ItemStack("hb_cb:kettle_item");
      world.getDimension(kettle.dimension.id).spawnItem(spawnedItem, kettle.location);
      kettle.remove();
    });
  }

  getRecipeOutput(input1, input2) {
    for (const recipe of recipes) {
      if ((recipe.input1 === input1 && recipe.input2 === input2) || (recipe.input1 === input2 && recipe.input2 === input1)) {
        return recipe.output;
      }
    }
    return null; // Return null if no matching recipe is found
  }

  isHeldItemAnInput(heldItem) {
    let otherItem = false;
    // Loop through each recipe
    for (const recipe of recipes) {
      if (recipe.input1 === heldItem || recipe.input2 === heldItem) {
        ////////world.sendMessage("recipe item");
        return true;
      }
    }
    foodItems.forEach((item) => {
      if (item === heldItem) {
        otherItem = true;
      }
    });
    if (otherItem) {
      ////////world.sendMessage("not a recipe item, but match");
      return true;
    }
    ////////world.sendMessage("not mathcing item");
    return false; // If no match found
  }
}
