export const PREVIEW_MODES = Object.freeze(["fit", "actual"]);

const DEFAULT_RESOLUTION = 68;
const MIN_RESOLUTION = 8;
const MAX_RESOLUTION = 96;
const FIT_INSET = 0.075;

function finite(value, fallback) {
  return Number.isFinite(Number(value)) ? Number(value) : fallback;
}

export function normalizePreviewMode(mode) {
  return mode === "actual" ? "actual" : "fit";
}

export function normalizePreviewResolution(resolution) {
  return Math.min(
    MAX_RESOLUTION,
    Math.max(
      MIN_RESOLUTION,
      Math.round(finite(resolution, DEFAULT_RESOLUTION)),
    ),
  );
}

export function previewModeDetails(mode, resolution) {
  const normalizedMode = normalizePreviewMode(mode);
  const normalizedResolution = normalizePreviewResolution(resolution);
  return {
    mode: normalizedMode,
    resolution: normalizedResolution,
    cellSize: normalizedMode === "actual" ? 1 : null,
    footprint: normalizedMode === "actual" ? normalizedResolution : null,
  };
}

export function canvasGridLayout(mode, resolution, width, height) {
  const details = previewModeDetails(mode, resolution);
  const safeWidth = Math.max(1, finite(width, details.resolution));
  const safeHeight = Math.max(1, finite(height, details.resolution));

  if (details.mode === "actual") {
    const stageSize = details.resolution;
    return {
      ...details,
      stageSize,
      cellSize: 1,
      offsetX: Math.round((safeWidth - stageSize) / 2),
      offsetY: Math.round((safeHeight - stageSize) / 2),
    };
  }

  const shortSide = Math.min(safeWidth, safeHeight);
  const margin = shortSide * FIT_INSET;
  const stageSize = shortSide - margin * 2;
  return {
    ...details,
    stageSize,
    cellSize: stageSize / details.resolution,
    offsetX: (safeWidth - stageSize) / 2,
    offsetY: (safeHeight - stageSize) / 2,
  };
}
