import vehiclesValues from "./VehicleValues.js";
import highlightBlock from "./MultiblockHighlight.js";

export {
  takeoffSpeed,
  takeOffFlight,
  vehicleCheck,
  vehicleSpeed,
  isAirInFrontAndBelow,
  sendDevMessage,
  isVehicleInWater,
  getEnvironment,
  applyAcceleration,
  applyDeceleration,
  setHoverState,
};

function takeoffSpeed(driver, vehicle, hasFuel, speed, vehicleData) {
  if (!hasFuel) {
    driver.setDynamicProperty("canTakeOff", false);
    return;
  }

  const canTakeOff = driver.getDynamicProperty("canTakeOff");

  if (speed == 0 && vehicle.isOnGround) {
    driver.onScreenDisplay.setActionBar("Hold Jump To Accelerate");
    driver.setDynamicProperty("canTakeOff", false);
  }
  if (speed > 0 && speed < vehicleData.take_off && vehicle.isOnGround) {
    driver.onScreenDisplay.setActionBar("Increase Speed To Take-Off");
    driver.setDynamicProperty("canTakeOff", false);
  }
  if (speed >= vehicleData.take_off && vehicle.isOnGround) {
    driver.onScreenDisplay.setActionBar("Look Up To Take-Off");
    driver.setDynamicProperty("canTakeOff", true);
  }
  /*   if (speed < vehicleData.take_off && !vehicle.isOnGround) {
    driver.onScreenDisplay.setActionBar(
      "Speed Dropping - Hold Jump To Avoid Falling"
    );
    driver.setDynamicProperty("canTakeOff", false);
  } */
  if (speed >= vehicleData.take_off * 0.7 && !vehicle.isOnGround) {
    driver.setDynamicProperty("canTakeOff", true);
  }

  return canTakeOff;
}

// SWITCH MODE - if plane speed is enough, switch to flight
function takeOffFlight(driver, vehicle, hasFuel) {
  const takeOff = driver.getDynamicProperty("canTakeOff");
  const viewDirection = parseFloat(driver?.getViewDirection().y.toFixed(2));
  const events = [
    {
      condition: hasFuel && takeOff && viewDirection >= 0.5 && driver.isJumping, // player is jumping and moving upwards
      effect: "ascend_fast",
      amplifier: Math.floor(viewDirection * 0.35 * 100),
    },
    {
      condition:
        hasFuel &&
        takeOff &&
        viewDirection >= 0.2 &&
        viewDirection < 0.5 &&
        driver.isJumping, // player is jumping and moving upwards
      effect: "ascend_slow",
      amplifier: viewDirection,
    },
    {
      condition:
        hasFuel &&
        takeOff &&
        viewDirection >= -0.2 &&
        viewDirection < 0.2 &&
        driver.isJumping, // player is jumping and moving upwards
      effect: "maintain",
    },
    {
      condition:
        hasFuel &&
        viewDirection >= -0.5 &&
        viewDirection < -0.2 &&
        driver.isJumping, // player is jumping and moving upwards
      effect: "descend_slow",
      amplifier: 1,
    },
    {
      condition:
        hasFuel &&
        viewDirection < -0.5 &&
        viewDirection >= -0.8 &&
        driver.isJumping, // player is jumping and moving upwards
      effect: "descend_fast",
      amplifier: 0,
    },
    {
      condition: !driver.isJumping || !hasFuel,
      effect: "gliding",
      amplifier: 1,
    },
    { condition: viewDirection <= -0.8, effect: "descend_fall", amplifier: 0 },
  ];
  vehicle?.removeEffect("levitation");
  vehicle?.removeEffect("slow_falling");

  const { effect, amplifier } = events.find(({ condition }) => condition) || {};

  if (effect === "ascend_fast") {
    driver.onScreenDisplay.setActionBar("Plane Ascending Fast");
    vehicle?.addEffect("levitation", 20, {
      amplifier: amplifier,
      showParticles: false,
    });
  }
  if (effect === "ascend_slow") {
    driver.onScreenDisplay.setActionBar("Plane Ascending");
    const ascendValue = Math.max(0.08, Math.min(viewDirection / 2, 0.12));
    vehicle?.applyImpulse({ x: 0, y: ascendValue, z: 0 });
  }
  if (effect === "maintain") {
    vehicle?.applyImpulse({ x: 0, y: 0.0784, z: 0 });
    driver.onScreenDisplay.setActionBar("Holding Altitude");
  }
  if (effect == "descend_slow") {
    driver.onScreenDisplay.setActionBar("Plane Descending");
    vehicle?.addEffect("slow_falling", 20, {
      amplifier: amplifier,
      showParticles: false,
    });
  }
  if (effect == "descend_fast") {
    driver.onScreenDisplay.setActionBar("Plane Descending Fast");
    vehicle?.addEffect("slow_falling", 20, {
      amplifier: amplifier,
      showParticles: false,
    });
  }
  if (effect == "descend_fall") {
    driver.onScreenDisplay.setActionBar("Plane Plummeting");
    vehicle?.removeEffect("levitation");
    vehicle?.removeEffect("slow_falling");
  }
  if (effect == "gliding") {
    driver.onScreenDisplay.setActionBar("Plane Gliding");
    vehicle?.addEffect("slow_falling", 20, {
      amplifier: amplifier,
      showParticles: false,
    });
  }
}

function setHoverState(driver, vehicle) {
  // sets the hoverstate if the player double taps the ascend button in a 75-300ms timeframe.
  let timeElapsed =
    driver.getDynamicProperty("end") - driver.getDynamicProperty("start");
  if (timeElapsed > 75 && timeElapsed < 300) {
    vehicle?.addTag("pb_dino_hovering");
    return true;
  } else {
    vehicle?.removeEffect("slow_falling");
    vehicle?.addEffect("levitation", 20, {
      amplifier: 5,
      showParticles: false,
    });
    vehicle?.removeTag("pb_dino_hovering");
    return false;
  }
}

function vehicleCheck(player) {
  const entityRidingOn =
    player.getComponent("minecraft:riding")?.entityRidingOn?.typeId;
  if (!entityRidingOn) return false;
  return Object.values(vehiclesValues).some(
    (vehicle) => vehicle.typeId === entityRidingOn
  );
}

function vehicleSpeed(vehicle) {
  const velocity = vehicle.getVelocity();
  return Math.sqrt(velocity.x ** 2 + velocity.z ** 2);
}

function applyAcceleration(vehicle, driver, impulseAmount) {
  const viewDirection = driver.getViewDirection();
  vehicle.applyImpulse({
    x: viewDirection.x * impulseAmount,
    y: 0,
    z: viewDirection.z * impulseAmount,
  });
}

function isAirInFrontAndBelow(vehicle, driver) {
  if (vehicle.location.y >= 300 || vehicle.location.y <= 5) {
    return false; // Default value when above altitude limit
  }
  const viewDirection = vehicle.getViewDirection();
  const x = Math.floor(vehicle.location.x + viewDirection.x);
  const y = Math.floor(vehicle.location.y);
  const z = Math.floor(vehicle.location.z + viewDirection.z);
  const blockAhead = vehicle.dimension.getBlock({ x, y, z });
  highlightBlockIfDev(driver, blockAhead, "green"); // Use the new function for highlighting
  return blockAhead.typeId === "minecraft:air";
}

// Helper function to send messages for debugging
function sendDevMessage(driver, message) {
  if (driver.hasTag("pb_dev_info")) {
    driver.onScreenDisplay.setActionBar(message);
  }
}

// Helper function to highlight blocks with the dev tag check
function highlightBlockIfDev(driver, block, color) {
  if (driver.hasTag("pb_dev_info")) {
    highlightBlock(block, color); // Call highlightBlock only if the player has the tag
  }
}

// Function to check if the vehicle is in water
function isVehicleInWater(vehicle) {
  const vehiclePosition = vehicle.location; // Get the vehicle's position
  const dimension = vehicle.dimension; // Get the dimension of the vehicle
  // Check the block directly below the vehicle
  const blockBelow = dimension.getBlock({
    x: Math.floor(vehiclePosition.x),
    y: Math.floor(vehiclePosition.y),
    z: Math.floor(vehiclePosition.z),
  });

  // Check if the block below is water
  return blockBelow && blockBelow.typeId === "minecraft:water";
}

// Function to check the environment (Ground, Water, or Air)
function getEnvironment(vehicle) {
  if (isVehicleInWater(vehicle)) {
    return "Water";
  } else if (vehicle.isOnGround) {
    return "Ground";
  } else {
    return "Air";
  }
}

// Function to apply impulse for movement (deceleration)
function applyDeceleration(vehicle, driver, impulseAmount, airDrag) {
  const viewDirection = driver.getViewDirection();

  vehicle.applyImpulse({
    x: viewDirection.x * (impulseAmount * airDrag * 0.6),
    y: 0,
    z: viewDirection.z * (impulseAmount * airDrag * 0.6),
  });
}
