
// Special-case parser for 0xF0 (XDEV CMD): implement multi-mode parsing.
// Rules:
// - A line that begins with exactly two spaces ("  ") and then a non-* character starts a new mode; the trimmed text is modeName.
// - Lines with three or more leading spaces (>=3) belong to the current mode.
// - A line with exactly two spaces followed by '*' is a parent (register-level) note, not a mode note.
// - Inside access blocks for F0, lines starting with '*' are headings for description (not notes).
import { Register, RegisterAccess, RegisterDetail, detailHasContent, isIssueRestricted } from "@/utils/register_parser";

export const parseDescriptionF0 = (reg: Register, description: string) => {
  const descriptionLines = description.split('\n');
  let currentAccess: 'read' | 'write' | 'common' | null = null;
  let accessData: RegisterAccess = { operations: [], notes: [] };
  // Prepare a new RegisterDetail for this description block
  let detail: RegisterDetail = { read: undefined, write: undefined, common: undefined, text: ''};
  reg.modes = reg.modes || [];

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

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

    if(spaces_at_start == 2) {
      if (trimmedLine.startsWith('*')) {
        const noteMatch = trimmedLine.match(/^(\*+)\s*(.*)/);
        if (noteMatch) {
          reg.notes.push({
            ref: noteMatch[1],
            text: noteMatch[2],
          });
        }
        continue;
      } else {
        if (currentAccess) {
          // finalize previous access block into detail
          detail[currentAccess] = accessData;
        }
        // Skip the initial blank detail that precedes the first mode header.
        if (detailHasContent(detail)) {
          reg.modes.push(detail);
        }
        detail = {read: undefined, write: undefined, common: undefined, text: ''};
        detail.modeName = trimmedLine;

        accessData = {operations: [], notes: []};
        currentAccess = null;
        continue;
      }
    }

    if (isIssueRestricted(line)) reg.issue_4_only = true;


    if (trimmedLine.startsWith('//')) continue;

    if (trimmedLine.startsWith('(R)')) {
      if (currentAccess) {
        // finalize previous access block into detail
        detail[currentAccess] = accessData;
      }
      accessData = { operations: [], notes: [] };
      currentAccess = 'read';
      continue;
    }
    if (trimmedLine.startsWith('(W)')) {
      if (currentAccess) {
        detail[currentAccess] = accessData;
      }
      accessData = { operations: [], notes: [] };
      currentAccess = 'write';
      continue;
    }
    if (trimmedLine.startsWith('(R/W')) {
      if (currentAccess) {
        detail[currentAccess] = accessData;
      }
      accessData = { operations: [], notes: [] };
      currentAccess = 'common';
      continue;
    }

    if (currentAccess) {
      const bitMatch = trimmedLine.match(/^(bits?|bit)\s+([\d:-]+)\s*=\s*(.*)/);
      const valueMatch = !line.match(/^\s+/) && trimmedLine.match(/^([01\s]+)\s*=\s*(.*)/);

      if (bitMatch) {
        let bitDescription = bitMatch[3];
        const footnoteMatch = bitDescription.match(/(\*+)$/);
        let footnoteRef: string | undefined = undefined;
        if (footnoteMatch) {
          footnoteRef = footnoteMatch[1];
          bitDescription = bitDescription.substring(0, bitDescription.length - footnoteRef.length).trim();
        }
        accessData.operations.push({
          bits: bitMatch[2],
          description: bitDescription,
          footnoteRef: footnoteRef,
        });
      } else if (valueMatch) {
        accessData.operations.push({
          bits: valueMatch[1].trim().replace(/\s/g, ''),
          description: valueMatch[2].trim(),
        });
      } else if (trimmedLine.startsWith('*') && spaces_at_start > 2) {
        const noteMatch = trimmedLine.match(/^(\*+)\s*(.*)/);
        if (noteMatch) {
          reg.notes.push({
            ref: noteMatch[1],
            text: noteMatch[2],
          });
        }
      }
    } else if (trimmedLine) {
      // Prose outside any access block (the leading "R/W Issues 4 and 5 Only -
      // (soft reset = 0x80)" line) is register-level commentary.
      reg.text += `${trimmedLine}\n`;
    }
  }
  if (currentAccess) {
    detail[currentAccess] = accessData;
  }

  // Push the final mode's detail into modes (if it carries content).
  if (detailHasContent(detail)) {
    reg.modes.push(detail);
  }
};
