import { FieldType, type Segment } from "@hamradio/packet";

import { DO_NOT_ARCHIVE_MARKER, DataType, type MessagePayload, type Payload } from "./frame.types";

export const decodeMessagePayload = (
  rawPayload: string,
  withStructure: boolean = false
): {
  payload: Payload | null;
  segment?: Segment[];
} => {
  // Message format: :AAAAAAAAA[ ]:message text
  // where AAAAAAAAA is a 9-character recipient field (padded with spaces)
  if (rawPayload.length < 2) return { payload: null };

  let offset = 1; // skip ':' data type
  const segments: Segment[] = withStructure ? [] : [];

  // Attempt to read a 9-char recipient field if present
  let recipient = "";
  if (rawPayload.length >= offset + 1) {
    // Try to read up to 9 chars for recipient, but stop early if a ':' separator appears
    const look = rawPayload.substring(offset, Math.min(offset + 9, rawPayload.length));
    const sepIdx = look.indexOf(":");
    let raw = look;
    if (sepIdx !== -1) {
      raw = look.substring(0, sepIdx);
    } else if (look.length < 9 && rawPayload.length >= offset + 9) {
      // pad to full 9 chars if possible
      raw = rawPayload.substring(offset, offset + 9);
    } else if (look.length === 9) {
      raw = look;
    }

    recipient = raw.trimEnd();
    if (withStructure) {
      segments.push({
        name: "recipient",
        data: new TextEncoder().encode(raw).buffer,
        isString: true,
        fields: [{ type: FieldType.STRING, name: "to", length: 9 }]
      });
    }

    // Advance offset past the raw we consumed
    offset += raw.length;
    // If there was a ':' immediately after the consumed raw, skip it as separator
    if (rawPayload.charAt(offset) === ":") {
      offset += 1;
    } else if (sepIdx !== -1) {
      // Shouldn't normally happen, but ensure we advance past separator
      offset += 1;
    }
  }

  // After recipient there is typically a space and a colon separator before the text
  // Find the first ':' after the recipient (it separates the address field from the text)
  let textStart = rawPayload.indexOf(":", offset);
  if (textStart === -1) {
    // No explicit separator; skip any spaces and take remainder as text
    while (rawPayload.charAt(offset) === " " && offset < rawPayload.length) offset += 1;
    textStart = offset - 1;
  }

  let text = "";
  if (textStart >= 0 && textStart + 1 <= rawPayload.length) {
    text = rawPayload.substring(textStart + 1);
  }
  const doNotArchive = text.includes(DO_NOT_ARCHIVE_MARKER);

  const payload: MessagePayload = {
    type: DataType.Message,
    variant: "message",
    doNotArchive,
    addressee: recipient,
    text
  };

  if (withStructure) {
    // Emit text section
    segments.push({
      name: "text",
      data: new TextEncoder().encode(text).buffer,
      isString: true,
      fields: [{ type: FieldType.STRING, name: "text", length: text.length }]
    });

    return { payload, segment: segments };
  }

  return { payload };
};

export default decodeMessagePayload;
