export var COLLIDER_STORAGE_KEY = 'bomzhara:map-colliders:v1';
export var MAP_COLLIDER_VERSION = 2;

// Fractions of the gameplay arena rectangle, not raw pixels.
var DEFAULT_SOLID_DEFS = [
  { id: 'top-left-wall', x: 0.13, y: 0.08, w: 0.25, h: 0.13 },
  { id: 'top-right-wall', x: 0.59, y: 0.08, w: 0.28, h: 0.13 },
  { id: 'left-outer-wall', x: 0.10, y: 0.17, w: 0.07, h: 0.54 },
  { id: 'right-outer-wall-upper', x: 0.82, y: 0.18, w: 0.07, h: 0.30 },
  { id: 'right-outer-wall-lower', x: 0.84, y: 0.49, w: 0.06, h: 0.32 },
  { id: 'bottom-left-room-wall', x: 0.13, y: 0.69, w: 0.22, h: 0.13 },
  { id: 'bottom-center-wall', x: 0.37, y: 0.78, w: 0.16, h: 0.08 },
  { id: 'bottom-right-wall', x: 0.61, y: 0.73, w: 0.27, h: 0.11 },
  { id: 'bathroom-partition', x: 0.61, y: 0.13, w: 0.05, h: 0.34 },
  { id: 'right-stairwell', x: 0.70, y: 0.32, w: 0.11, h: 0.27 },
  { id: 'burn-barrel', x: 0.18, y: 0.33, w: 0.06, h: 0.08 },
  { id: 'lit-table-clutter', x: 0.63, y: 0.63, w: 0.13, h: 0.10 },
];

export var DEFAULT_ENEMY_HOLE_DEFS = [
  { id: 'enemy-hole-top-window', type: 'enemy-hole', x: 0.24, y: 0.075, w: 0.10, h: 0.09 },
  { id: 'enemy-hole-right-stairs', type: 'enemy-hole', x: 0.855, y: 0.34, w: 0.07, h: 0.17 },
  { id: 'enemy-hole-bottom-door', type: 'enemy-hole', x: 0.43, y: 0.765, w: 0.17, h: 0.09 },
  { id: 'enemy-hole-left-breach', type: 'enemy-hole', x: 0.085, y: 0.38, w: 0.09, h: 0.18 },
];

export var DEFAULT_MAP_SOLID_DEFS = DEFAULT_SOLID_DEFS.concat(DEFAULT_ENEMY_HOLE_DEFS);

function num(v, fallback) {
  v = Number(v);
  return Number.isFinite(v) ? v : fallback;
}

function clamp(v, lo, hi) {
  return Math.max(lo, Math.min(hi, v));
}

function safeId(v, i) {
  v = String(v || '').trim().replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, '');
  return v || ('collider-' + (i + 1));
}

function safeType(v) {
  return v === 'enemy-hole' ? 'enemy-hole' : 'solid';
}

function hasEnemyHoles(defs) {
  for (var i = 0; i < defs.length; i++) if (defs[i].type === 'enemy-hole') return true;
  return false;
}

export function sanitizeMapSolidDefs(input) {
  if (!Array.isArray(input)) return [];
  var out = [];
  for (var i = 0; i < input.length; i++) {
    var d = input[i] || {};
    var w = clamp(num(d.w, 0.08), 0.005, 1);
    var h = clamp(num(d.h, 0.08), 0.005, 1);
    var x = clamp(num(d.x, 0.46), 0, 1 - w);
    var y = clamp(num(d.y, 0.46), 0, 1 - h);
    out.push({
      id: safeId(d.id, i),
      type: safeType(d.type),
      x: +x.toFixed(4),
      y: +y.toFixed(4),
      w: +w.toFixed(4),
      h: +h.toFixed(4),
    });
  }
  return out;
}

export function cloneMapSolidDefs(defs) {
  return sanitizeMapSolidDefs(defs || DEFAULT_MAP_SOLID_DEFS);
}

export function loadStoredMapSolidDefs() {
  if (typeof window === 'undefined' || !window.localStorage) return null;
  try {
    var raw = window.localStorage.getItem(COLLIDER_STORAGE_KEY);
    if (!raw) return null;
    var parsed = JSON.parse(raw);
    var colliders = Array.isArray(parsed) ? parsed : parsed && parsed.colliders;
    var version = Array.isArray(parsed) ? 0 : num(parsed && parsed.version, 0);
    var clean = sanitizeMapSolidDefs(colliders);
    if (clean.length && version < 2 && !hasEnemyHoles(clean)) {
      clean = clean.concat(sanitizeMapSolidDefs(DEFAULT_ENEMY_HOLE_DEFS));
    }
    return clean.length ? clean : null;
  } catch (e) {
    return null;
  }
}

export function hasStoredMapSolidDefs() {
  return !!loadStoredMapSolidDefs();
}

export function loadMapSolidDefs() {
  return loadStoredMapSolidDefs() || cloneMapSolidDefs(DEFAULT_MAP_SOLID_DEFS);
}

export function saveStoredMapSolidDefs(defs) {
  var clean = sanitizeMapSolidDefs(defs);
  if (!clean.length) throw new Error('No colliders to save');
  if (typeof window === 'undefined' || !window.localStorage) throw new Error('localStorage unavailable');
  window.localStorage.setItem(COLLIDER_STORAGE_KEY, JSON.stringify({
    version: MAP_COLLIDER_VERSION,
    colliders: clean,
  }, null, 2));
  return clean;
}

export function clearStoredMapSolidDefs() {
  if (typeof window !== 'undefined' && window.localStorage) window.localStorage.removeItem(COLLIDER_STORAGE_KEY);
}

export function formatMapSolidDefs(defs) {
  return JSON.stringify({
    version: MAP_COLLIDER_VERSION,
    colliders: sanitizeMapSolidDefs(defs),
  }, null, 2);
}

export function formatSourceSnippet(defs) {
  var clean = sanitizeMapSolidDefs(defs);
  var solids = [];
  var holes = [];
  for (var i = 0; i < clean.length; i++) {
    if (clean[i].type === 'enemy-hole') holes.push(clean[i]);
    else solids.push(clean[i]);
  }
  return [
    '// Replace the default collider block in map-colliders.js with this before building a zip.',
    '// These are fractions of the rendered map/arena rectangle, not raw pixels.',
    'var DEFAULT_SOLID_DEFS = ' + JSON.stringify(solids, null, 2) + ';',
    '',
    'export var DEFAULT_ENEMY_HOLE_DEFS = ' + JSON.stringify(holes, null, 2) + ';',
    '',
    'export var DEFAULT_MAP_SOLID_DEFS = DEFAULT_SOLID_DEFS.concat(DEFAULT_ENEMY_HOLE_DEFS);',
    '',
  ].join('\n');
}
