import { LootTables } from "./loot-tables.js";
import { getSellValue } from "./economy.js";
import { getIncomeMultiplier } from "./mutation-rules.js";

const CELL_PITCH = 52;
const GRID_PADDING = 6;
const CELL_CENTER_OFFSET = 24;

/**
 * Center of a cell in layer pixel coordinates (1-based x, y).
 * @param {number} x 1-based column
 * @param {number} y 1-based row
 * @returns {{ cx: number, cy: number }}
 */
function cellCenterPx(x, y) {
  const cx = GRID_PADDING + (x - 1) * CELL_PITCH + CELL_CENTER_OFFSET;
  const cy = GRID_PADDING + (y - 1) * CELL_PITCH + CELL_CENTER_OFFSET;
  return { cx, cy };
}

/**
 * Weighted center of the zoo by animal value (sell value). Visitors are attracted to expensive animals.
 * @param {import("./types.js").GameState} state
 * @param {number} gridWidth
 * @param {number} gridHeight
 * @returns {{ centerX: number, centerY: number }}
 */
export function getAttractionCenter(state, gridWidth, gridHeight) {
  let sumW = 0;
  let sumWx = 0;
  let sumWy = 0;
  for (const [key, cell] of Object.entries(state.grid.cells)) {
    if (cell.kind === "animal") {
      const def = LootTables.Animals[cell.id];
      if (def !== null && def !== undefined) {
        const mut = getIncomeMultiplier(cell.mutation ?? "none");
        const w = getSellValue(def.baseIncomePerSecond, cell.level ?? 1, mut, def.sellFactor);
        const [x, y] = key.split("_").map(Number);
        const { cx, cy } = cellCenterPx(x, y);
        sumW += w;
        sumWx += w * cx;
        sumWy += w * cy;
      }
    }
  }
  if (sumW <= 0) {
    const cx = GRID_PADDING + (gridWidth * CELL_PITCH - 4) / 2;
    const cy = GRID_PADDING + (gridHeight * CELL_PITCH - 4) / 2;
    return { centerX: cx, centerY: cy };
  }
  return {
    centerX: sumWx / sumW,
    centerY: sumWy / sumW,
  };
}

/**
 * Cell key (1-based x, y) at the given pixel position in the grid layer.
 * @param {number} px
 * @param {number} py
 * @param {number} gridWidth
 * @param {number} gridHeight
 * @returns {string} key "x_y" or empty if out of bounds
 */
export function getCellKeyFromPixelPosition(px, py, gridWidth, gridHeight) {
  const x = 1 + Math.round((px - GRID_PADDING - CELL_CENTER_OFFSET) / CELL_PITCH);
  const y = 1 + Math.round((py - GRID_PADDING - CELL_CENTER_OFFSET) / CELL_PITCH);
  if (x < 1 || x > gridWidth || y < 1 || y > gridHeight) return "";
  return `${x}_${y}`;
}

/**
 * Unique position for visitor i: orbits around the attraction center with per-visitor phase, radius and speed.
 * A second harmonic gives figure-8 / Lissajous-style paths so each visitor has a distinct walk.
 * @param {{ i: number, n: number, t: number, centerX: number, centerY: number, gridWidth: number, gridHeight: number }} opts
 * @returns {{ px: number, py: number }}
 */
export function getVisitorPosition(opts) {
  const { i, n, t, centerX, centerY, gridWidth, gridHeight } = opts;
  const phase1 = (i / Math.max(1, n)) * Math.PI * 2 + ((i * 17) % 100) * 0.01;
  const phase2 = ((i * 13) % 100) * 0.063;
  const radius1 = 28 + (i * 31) % 55;
  const radius2 = 12 + (i * 11) % 18;
  const speed1 = 0.15 + ((i * 7) % 50) * 0.008;
  const speed2 = 0.08 + ((i * 19) % 40) * 0.006;
  const angle1 = phase1 + t * speed1;
  const angle2 = phase2 + t * speed2;
  const px = centerX + radius1 * Math.cos(angle1) + radius2 * Math.cos(angle2 * 1.3);
  const py = centerY + radius1 * Math.sin(angle1) + radius2 * Math.sin(angle2 * 0.9);
  const minX = GRID_PADDING;
  const minY = GRID_PADDING;
  const maxX = GRID_PADDING + gridWidth * CELL_PITCH - 4 - 20;
  const maxY = GRID_PADDING + gridHeight * CELL_PITCH - 4 - 20;
  return {
    px: Math.max(minX, Math.min(maxX, px)),
    py: Math.max(minY, Math.min(maxY, py)),
  };
}
