import { world, system } from "@minecraft/server";
import { blackHole_MAIN } from "./black_hole";
import { whiteHole_MAIN } from "./white_hole";
import { tornado_MAIN } from "./tornado";
import { meteor_MAIN } from "./meteor";
import { highPressureGenerator_MAIN } from "./high_pressure_generator";
import { get_randomDayTick } from "./time_events";
import {
  meteoriteScheldule,
  tornadoScheldule,
  summonTornadoInRainWeather,
  black_holeScheldule,
} from "./scheldules";
import {
  itemUseOn_recipes,
  itemUse_fabricOfReality,
  itemUse_TestItem,
} from "./use_on_block_recipes";
import { torches_event_MAIN } from "./torches_mutiny";
import { earthquake_MAIN } from "./earthquake";
import { swarm_of_bees_MAIN } from "./bees_attack";
import { skeleton_attack_MAIN } from "./skeleton_attack";
import { zombie_attack_MAIN } from "./zombie_attack";
import { blood_moon_MAIN } from "./blood_moon";
import { sticky_rain_MAIN } from "./sticky_rain";
import { solar_eclipse_MAIN } from "./solar_eclipse";
import { orbitalCanon_MAIN } from "./orbital_canon";
import { bookTick } from "./guide_book.js";
import { coloredSlimesDie } from "./colored_slime";
import "./enchanted_clock";
import "./durability";
import "./piston_unmovable";
import "./evil_eye.js";
import {
  AllEventProp,
  CurrentEventProp,
  AnyEventAtDayChance,
  anyPlayerNotUnderground,
  anyPlayerInDimension,
  resetAllConfigs,
  //blockCoordinatesHelper,
} from "./utilities";

//blockCoordinatesHelper(true, false, false);

export const tornadoSaverId = "tvf_randev:torndoSaver";

world.afterEvents.worldLoad.subscribe(() => {
  //welcome message
  //world.sendMessage("Random Events Add-On loaded v0.0.1!");

  const dimension = {
    overworld: world.getDimension("overworld"),
    nether: world.getDimension("nether"),
    end: world.getDimension("the_end"),
  };

  //check if first join
  if (!world.scoreboard.getObjective("tvf_randev_first_join")) {
    world.scoreboard.addObjective("tvf_randev_first_join");
    resetAllConfigs();
  }
  //локации far render для tornado чистится при загрузке мира
  world.setDynamicProperty(tornadoSaverId, JSON.stringify({}));
  //random event system
  system.runInterval(() => {
    const plannedEvent = CurrentEventProp.getProp();
    //plan event tick
    if (
      world.getTimeOfDay() == 1000 &&
      Math.random() <= AnyEventAtDayChance.getValue() * 0.01
    ) {
      planningEventTick();
    }
    if (plannedEvent.status == "is_planned") {
      //warning tick
      if (world.getTimeOfDay() == plannedEvent.planned_tick - 20 * 30) {
        if (anyPlayerInDimension(plannedEvent.dimension)) {
          if (
            (plannedEvent.only_on_surface == true &&
              anyPlayerNotUnderground() == true) ||
            plannedEvent.only_on_surface == false
          ) {
            world.sendMessage([
              {
                translate: `tvf_randev.event.warn.${plannedEvent.id}`,
              },
            ]);
          }
        }
      }
      //start tick
      if (world.getTimeOfDay() == plannedEvent.planned_tick) {
        if (anyPlayerInDimension(plannedEvent.dimension)) {
          if (
            (plannedEvent.only_on_surface == true &&
              anyPlayerNotUnderground() == true) ||
            plannedEvent.only_on_surface == false
          ) {
            plannedEvent.status = "is_happening";
            CurrentEventProp.update(plannedEvent);
          }
        }
      }
    }
  });

  //non random (Schelduled) events handlers
  system.runInterval(() => {
    meteoriteScheldule(dimension.overworld);
  });
  system.runInterval(() => {
    tornadoScheldule(dimension.overworld);
  }, 20);
  summonTornadoInRainWeather(dimension.overworld);
  system.runInterval(() => {
    black_holeScheldule(dimension.overworld);
  }, 20);
  //entity mechanics
  bookTick(dimension);
  coloredSlimesDie();
  blackHole_MAIN([dimension.overworld, dimension.nether, dimension.end]);
  whiteHole_MAIN([dimension.overworld, dimension.nether, dimension.end]);
  tornado_MAIN(dimension.overworld);
  meteor_MAIN(dimension.overworld);
  highPressureGenerator_MAIN(dimension.overworld);
  orbitalCanon_MAIN(dimension.overworld);
  //item use
  itemUseOn_recipes();
  itemUse_fabricOfReality("tvf_randev:fabric_of_reality");
  itemUse_TestItem("tvf_randev:creative_fabric");
  //random events in progress
  torches_event_MAIN(dimension.overworld);
  earthquake_MAIN(dimension.overworld);
  swarm_of_bees_MAIN(dimension.overworld);
  skeleton_attack_MAIN(dimension.overworld);
  blood_moon_MAIN(dimension.overworld);
  sticky_rain_MAIN(dimension.overworld);
  zombie_attack_MAIN(dimension.overworld);
  solar_eclipse_MAIN(dimension.overworld);
});
//

//Сбросить все настройки ивентов
//AllEventProp.update(eventConfig.eventsDefault)
//CurrentEventProp.update(eventConfig.currentEventDefault)

//Сброс тумана при спавне игрока
world.afterEvents.playerSpawn.subscribe((event) => {
  const player = event.player;
  if (!event.initialSpawn) return;
  //player dissconnect during event and reconnect after. Remove fog
  player.runCommand("/fog @s remove tvf_randev:fogsID");
});

//планировщик ивентв
function planningEventTick() {
  const availableEvents = AllEventProp.getAvailableRandomEvents();
  const currEvent = CurrentEventProp.getProp();
  // Удаляем предыдущее событие из доступных только если объектов больше или равно 3
  if (Object.keys(availableEvents).length >= 3) {
    delete availableEvents[currEvent.id];
  }
  const eventToStart = get_randomEvent(availableEvents);
  //console.warn('planned:' + eventToStart.id)
  //unused
  //if (eventToStart.id == 'none') return
  currEvent.id = eventToStart.id;
  currEvent.maxDuration = eventToStart.maxDuration;
  currEvent.status = "is_planned";
  currEvent.timer = 0;
  currEvent.planned_tick = get_randomDayTick(eventToStart.time);
  currEvent.forcedEnd = false;
  currEvent.dimension = eventToStart.dimension;
  currEvent.only_on_surface = eventToStart.only_on_surface;
  CurrentEventProp.update(currEvent);
}

//получить случайный ивент в зависимости от его веса, только с random: true
function get_randomEvent(events) {
  var wt = 0; // Сумма веса всех
  for (const [eventId, eventData] of Object.entries(events)) {
    eventData.bound = wt += eventData.w; // Определяем границу, которая зависит от веса
  }
  let r = Math.floor(Math.random() * wt + 1);
  for (const [eventId, eventData] of Object.entries(events)) {
    // Ищем какой попал в полученное случайное число
    if (r > eventData.bound - eventData.w && r <= eventData.bound) {
      return eventData;
    }
  }
}
