// Special-case parser for 0x44 (Palette Value, 9 bit colour).
// The 9-bit colour is written with two consecutive byte writes, each carrying
// its own bit layout. The source nests these under "1st write:" / "2nd write:"
// headers (two leading spaces, trailing colon) with their bit definitions
// indented beneath (four leading spaces):
//
//   (R/W)
//     Two consecutive writes are needed to write the 9 bit colour
//     1st write:
//       bits 7:0 = RRRGGGBB
//     2nd write:
//       bits 7:1 = Reserved, must be 0
//       ...
//
// Each write becomes its own mode with a single Read/Write access block so the
// two distinct bit layouts render as separate tables. Two-space prose outside a
// write header is register-level commentary; six-space lines continue the
// preceding bit definition.
import { Register, RegisterAccess, RegisterDetail, isIssueRestricted } from "@/utils/register_parser";

export const parseDescription44 = (reg: Register, description: string) => {
  const descriptionLines = description.split('\n');
  reg.modes = reg.modes || [];

  let currentDetail: RegisterDetail | null = null;
  let currentAccess: RegisterAccess | null = null;

  const finishDetail = () => {
    if (currentDetail && currentAccess) {
      currentDetail.common = currentAccess;
      reg.modes.push(currentDetail);
    }
    currentDetail = null;
    currentAccess = null;
  };

  for (const line of descriptionLines) {
    reg.source.push(line);
    reg.search += line.toLowerCase() + " ";

    const trimmedLine = line.trim();
    if (!trimmedLine) continue;
    if (trimmedLine.startsWith('//')) continue;
    if (isIssueRestricted(line)) reg.issue_4_only = true;

    const spaces_at_start = line.match(/^(\s*)/)?.[0].length || 0;

    // The lone "(R/W)" marker just confirms the access type; both writes are R/W.
    if (trimmedLine.startsWith('(R/W')) continue;

    // A write header: "1st write:", "2nd write:", etc. starts a new mode.
    if (spaces_at_start <= 2 && /^\d+(st|nd|rd|th)\s+write:?$/i.test(trimmedLine)) {
      finishDetail();
      currentDetail = { read: undefined, write: undefined, common: undefined, text: '' };
      currentDetail.modeName = trimmedLine.replace(/:$/, '');
      currentAccess = { operations: [], notes: [] };
      continue;
    }

    const bitMatch = trimmedLine.match(/^(bits?|bit)\s+([\d:-]+)\s*=\s*(.*)/);

    // Bit definitions live under a write header at deeper indentation.
    if (currentAccess && spaces_at_start >= 4 && bitMatch) {
      currentAccess.operations.push({
        bits: bitMatch[2],
        description: bitMatch[3].trim(),
      });
      continue;
    }

    // Six-space (or deeper) prose continues the previous bit definition.
    if (currentAccess && spaces_at_start >= 6 && currentAccess.operations.length > 0) {
      const ops = currentAccess.operations;
      ops[ops.length - 1].description += `\n${trimmedLine}`;
      continue;
    }

    // Four-space prose inside a write block is access-level description.
    if (currentAccess && spaces_at_start >= 4) {
      currentAccess.description = currentAccess.description
        ? `${currentAccess.description}\n${trimmedLine}`
        : trimmedLine;
      continue;
    }

    // Anything shallower (two-space prose outside a write block) is register commentary.
    reg.text += `${trimmedLine}\n`;
  }

  finishDetail();
};
