/**
 * Reticle drawing matching dsd-g1 Adafruit SSD1306 drawCrosshair / drawCrosshairScaled.
 * Custom pixels: absolute OLED offsets from center (1 cell = 1 OLED pixel).
 * Built-in 0–15: geometry scaled by boxScale (= scaleBox/9), same as firmware.
 */

export function fwRound(v) {
  return v >= 0 ? Math.trunc(v + 0.5) : Math.trunc(v - 0.5);
}

/** Adafruit GFX Bresenham drawLine */
export function drawLine(setPx, x0, y0, x1, y1) {
  x0 |= 0; y0 |= 0; x1 |= 0; y1 |= 0;
  const steep = Math.abs(y1 - y0) > Math.abs(x1 - x0);
  if (steep) {
    [x0, y0] = [y0, x0];
    [x1, y1] = [y1, x1];
  }
  if (x0 > x1) {
    [x0, x1] = [x1, x0];
    [y0, y1] = [y1, y0];
  }
  const dx = x1 - x0;
  const dy = Math.abs(y1 - y0);
  let err = dx / 2;
  let ystep = y0 < y1 ? 1 : -1;
  let y = y0;
  for (let x = x0; x <= x1; x++) {
    if (steep) setPx(y, x);
    else setPx(x, y);
    err -= dy;
    if (err < 0) {
      y += ystep;
      err += dx;
    }
  }
}

export function drawCirclePixels(setPx, cx, cy, r) {
  // Approx match: firmware style 2/4 use discrete angle samples, not full circle
}

/** Built-in style at center, boxScale = scaleBox/9 (firmware). viewScale usually 1. */
export function drawBuiltinStyle(setPx, cx, cy, style, boxScale = 1) {
  const sAll = boxScale;
  const s4 = fwRound(4 * sAll);
  const s3 = fwRound(3 * sAll);
  const s2 = fwRound(2 * sAll);
  const st = style | 0;

  if (st === 0) {
    drawLine(setPx, cx - s4, cy, cx + s4, cy);
    drawLine(setPx, cx, cy - s4, cx, cy + s4);
    setPx(cx, cy);
  } else if (st === 1) {
    setPx(cx, cy);
  } else if (st === 2) {
    for (let i = 0; i < 8; i++) {
      const rad = (i * Math.PI) / 4;
      setPx(cx + fwRound(s2 * Math.cos(rad)), cy + fwRound(s2 * Math.sin(rad)));
    }
    setPx(cx, cy);
  } else if (st === 3) {
    drawLine(setPx, cx, cy - s3, cx - s3, cy + s2);
    drawLine(setPx, cx - s3, cy + s2, cx + s3, cy + s2);
    drawLine(setPx, cx + s3, cy + s2, cx, cy - s3);
  } else if (st === 4) {
    const r = fwRound(3 * sAll);
    for (let i = 0; i < 12; i++) {
      const rad = (i * Math.PI) / 6;
      setPx(cx + fwRound(r * Math.cos(rad)), cy + fwRound(r * Math.sin(rad)));
    }
    drawLine(setPx, cx - s4, cy, cx + s4, cy);
    drawLine(setPx, cx, cy - s4, cx, cy + s4);
  } else if (st === 5) {
    drawLine(setPx, cx - s2, cy - s2, cx + s2, cy + s2);
    drawLine(setPx, cx + s2, cy - s2, cx - s2, cy + s2);
  } else if (st === 6) {
    setPx(cx, cy - s2);
    setPx(cx, cy);
    setPx(cx, cy + s2);
  } else if (st === 7) {
    const w = Math.max(1, fwRound(4 * sAll));
    // drawRect outline
    drawLine(setPx, cx - (w >> 1), cy - (w >> 1), cx - (w >> 1) + w - 1, cy - (w >> 1));
    drawLine(setPx, cx - (w >> 1), cy - (w >> 1) + w - 1, cx - (w >> 1) + w - 1, cy - (w >> 1) + w - 1);
    drawLine(setPx, cx - (w >> 1), cy - (w >> 1), cx - (w >> 1), cy - (w >> 1) + w - 1);
    drawLine(setPx, cx - (w >> 1) + w - 1, cy - (w >> 1), cx - (w >> 1) + w - 1, cy - (w >> 1) + w - 1);
  } else if (st === 8) {
    drawLine(setPx, cx - s3, cy - s3, cx + s3, cy + s3);
    drawLine(setPx, cx + s3, cy - s3, cx - s3, cy + s3);
  } else if (st === 9) {
    setPx(cx, cy - s2);
    setPx(cx - s2, cy + s2);
    setPx(cx + s2, cy + s2);
  } else if (st === 10) {
    drawLine(setPx, cx - s2, cy - s2, cx + s2, cy - s2);
    drawLine(setPx, cx - s2, cy - s2, cx - s2, cy + s2);
    drawLine(setPx, cx + s2, cy - s2, cx + s2, cy + s2);
  } else if (st === 11) {
    drawLine(setPx, cx, cy - s2, cx, cy + s2);
    drawLine(setPx, cx, cy - s2, cx - 1, cy - 1);
    drawLine(setPx, cx, cy - s2, cx + 1, cy - 1);
  } else if (st === 12) {
    drawLine(setPx, cx, cy - s2, cx - s2, cy + s2);
    drawLine(setPx, cx - s2, cy + s2, cx + s2, cy + s2);
    drawLine(setPx, cx + s2, cy + s2, cx, cy - s2);
  } else if (st === 13) {
    setPx(cx - s2, cy - s2);
    setPx(cx - s2, cy + s2);
    setPx(cx + s2, cy - s2);
    setPx(cx + s2, cy + s2);
  } else if (st === 14) {
    drawLine(setPx, cx - s3, cy - s3, cx + s3, cy + s3);
    drawLine(setPx, cx + s3, cy - s3, cx - s3, cy + s3);
    drawLine(setPx, cx - s4, cy - s3, cx - s2, cy - s3);
    drawLine(setPx, cx + s4, cy - s3, cx + s2, cy - s3);
    drawLine(setPx, cx - s4, cy + s3, cx - s2, cy + s3);
    drawLine(setPx, cx + s4, cy + s3, cx + s2, cy + s3);
  } else if (st === 15) {
    const r = Math.max(1, fwRound(2 * sAll));
    // head circle approx 8 samples
    for (let i = 0; i < 8; i++) {
      const rad = (i * Math.PI) / 4;
      setPx(cx + fwRound(r * Math.cos(rad)), cy - s4 + fwRound(r * Math.sin(rad)));
    }
    drawLine(setPx, cx, cy - s2, cx, cy + s2);
    drawLine(setPx, cx - s3, cy, cx + s3, cy);
    drawLine(setPx, cx, cy + s2, cx - s2, cy + s4);
    drawLine(setPx, cx, cy + s2, cx + s2, cy + s4);
  } else {
    drawLine(setPx, cx - s4, cy, cx + s4, cy);
    drawLine(setPx, cx, cy - s4, cx, cy + s4);
    setPx(cx, cy);
  }
}

/** Custom: each [dx,dy] is one OLED pixel relative to center (matches firmware after fix). */
export function drawCustomPixels(setPx, cx, cy, pixels) {
  for (const p of pixels || []) {
    if (!p || p.length < 2) continue;
    setPx(cx + (p[0] | 0), cy + (p[1] | 0));
  }
}

/** Device default crosshair center (LEFT_MARGIN + DISPLAY_WIDTH/2, HEIGHT/2). */
export const RETICLE_CX = 64;
export const RETICLE_CY = 32;
