import { isNode } from '../nodes/Node.mjs';
import { createStringifyContext, stringify } from './stringify.mjs';
import { indentComment, lineComment } from './stringifyComment.mjs';

function stringifyDocument(doc, options) {
  const lines = [];
  let hasDirectives = options.directives === true;
  if (options.directives !== false && doc.directives) {
    const dir = doc.directives.toString(doc);
    if (dir) {
      lines.push(dir);
      hasDirectives = true;
    } else if (doc.directives.docStart) hasDirectives = true;
  }
  if (hasDirectives) lines.push('---');
  const ctx = createStringifyContext(doc, options);
  const {
    commentString
  } = ctx.options;
  if (doc.commentBefore) {
    if (lines.length !== 1) lines.unshift('');
    const cs = commentString(doc.commentBefore);
    lines.unshift(indentComment(cs, ''));
  }
  let chompKeep = false;
  let contentComment = null;
  if (doc.contents) {
    if (isNode(doc.contents)) {
      if (doc.contents.spaceBefore && hasDirectives) lines.push('');
      if (doc.contents.commentBefore) {
        const cs = commentString(doc.contents.commentBefore);
        lines.push(indentComment(cs, ''));
      }
      // top-level block scalars need to be indented if followed by a comment
      ctx.forceBlockIndent = !!doc.comment;
      contentComment = doc.contents.comment;
    }
    const onChompKeep = contentComment ? undefined : () => chompKeep = true;
    let body = stringify(doc.contents, ctx, () => contentComment = null, onChompKeep);
    if (contentComment) body += lineComment(body, '', commentString(contentComment));
    if ((body[0] === '|' || body[0] === '>') && lines[lines.length - 1] === '---') {
      // Top-level block scalars with a preceding doc marker ought to use the
      // same line for their header.
      lines[lines.length - 1] = `--- ${body}`;
    } else lines.push(body);
  } else {
    lines.push(stringify(doc.contents, ctx));
  }
  if (doc.directives?.docEnd) {
    if (doc.comment) {
      const cs = commentString(doc.comment);
      if (cs.includes('\n')) {
        lines.push('...');
        lines.push(indentComment(cs, ''));
      } else {
        lines.push(`... ${cs}`);
      }
    } else {
      lines.push('...');
    }
  } else {
    let dc = doc.comment;
    if (dc && chompKeep) dc = dc.replace(/^\n+/, '');
    if (dc) {
      if ((!chompKeep || contentComment) && lines[lines.length - 1] !== '') lines.push('');
      lines.push(indentComment(commentString(dc), ''));
    }
  }
  return lines.join('\n') + '\n';
}

export { stringifyDocument };
