import { BeeError } from "../utils/error.js";
import { bmtHash } from "./bmt.js";
import { assertFlexBytes, bytesEqual, flexBytesAtOffset } from "../utils/bytes.js";
import { serializeBytes } from "./serialize.js";
import { makeSpan, SPAN_SIZE } from "./span.js";
export const MIN_PAYLOAD_SIZE = 1;
export const MAX_PAYLOAD_SIZE = 4096;
const CAC_SPAN_OFFSET = 0;
const CAC_PAYLOAD_OFFSET = CAC_SPAN_OFFSET + SPAN_SIZE;
/**
 * Creates a content addressed chunk and verifies the payload size.
 *
 * @param payloadBytes the data to be stored in the chunk
 */

export function makeContentAddressedChunk(payloadBytes) {
  const span = makeSpan(payloadBytes.length);
  assertFlexBytes(payloadBytes, MIN_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE);
  const data = serializeBytes(span, payloadBytes);
  return {
    data,
    span: () => span,
    payload: () => flexBytesAtOffset(data, CAC_PAYLOAD_OFFSET, MIN_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE),
    address: () => bmtHash(data)
  };
}
/**
 * Type guard for valid content addressed chunk data
 *
 * @param data          The chunk data
 * @param chunkAddress  The address of the chunk
 */

export function isValidChunkData(data, chunkAddress) {
  if (!(data instanceof Uint8Array)) return false;
  const address = bmtHash(data);
  return bytesEqual(address, chunkAddress);
}
/**
 * Asserts if data are representing given address of its chunk.
 *
 * @param data          The chunk data
 * @param chunkAddress  The address of the chunk
 *
 * @returns a valid content addressed chunk or throws error
 */

export function assertValidChunkData(data, chunkAddress) {
  if (!isValidChunkData(data, chunkAddress)) {
    throw new BeeError('Address of content address chunk does not match given data!');
  }
}