'use strict';

/**
 * Cálculo modular do tempo de deslocação no mapa mundial.
 *
 * Regra base:
 * - Cada 10 coordenadas percorridas demoram exatamente 1 minuto.
 * - Cada coordenada percorrida demora 6 segundos.
 * - A distância é calculada em linha reta, considerando X e Y.
 * - A viagem de regresso utiliza exatamente o mesmo tempo da ida.
 */
(() => {
  const VERSION = 3;
  const SECONDS_PER_COORDINATE = 6;
  const COORDINATES_PER_MINUTE = 60 / SECONDS_PER_COORDINATE;
  const MILLISECONDS_PER_SECOND = 1000;
  const MILLISECONDS_PER_MINUTE = 60 * MILLISECONDS_PER_SECOND;
  const MINIMUM_TRAVEL_MS = 1000;

  function safeCoordinate(value, fallback = 0) {
    const parsed = Number(value);
    return Number.isFinite(parsed) ? parsed : fallback;
  }

  function normalizePosition(position, fallback = { x: 0, y: 0 }) {
    return {
      x: safeCoordinate(position?.x, safeCoordinate(fallback?.x)),
      y: safeCoordinate(position?.y, safeCoordinate(fallback?.y))
    };
  }

  function distanceBetween(from, to) {
    const origin = normalizePosition(from);
    const destination = normalizePosition(to, origin);
    return Math.hypot(destination.x - origin.x, destination.y - origin.y);
  }

  function calculateTravelMs(from, to) {
    const distance = distanceBetween(from, to);
    const rawMs = distance * SECONDS_PER_COORDINATE * MILLISECONDS_PER_SECOND;
    return Math.max(MINIMUM_TRAVEL_MS, Math.round(rawMs));
  }

  function route(from, to) {
    const origin = normalizePosition(from);
    const destination = normalizePosition(to, origin);
    const distance = distanceBetween(origin, destination);
    const travelMs = calculateTravelMs(origin, destination);
    return {
      version: VERSION,
      from: origin,
      to: destination,
      distance,
      travelMs,
      secondsPerCoordinate: SECONDS_PER_COORDINATE,
      coordinatesPerMinute: COORDINATES_PER_MINUTE
    };
  }

  globalThis.ReinosMarchTravelTime = Object.freeze({
    VERSION,
    SECONDS_PER_COORDINATE,
    COORDINATES_PER_MINUTE,
    MILLISECONDS_PER_SECOND,
    MILLISECONDS_PER_MINUTE,
    MINIMUM_TRAVEL_MS,
    normalizePosition,
    distanceBetween,
    calculateTravelMs,
    route
  });
})();
