"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.File = File;
exports.Program = Program;
exports.BlockStatement = BlockStatement;
exports.Noop = Noop;
exports.Directive = Directive;
exports.DirectiveLiteral = DirectiveLiteral;
exports.InterpreterDirective = InterpreterDirective;
exports.Placeholder = Placeholder;

function File(node) {
  if (node.program) {
    this.print(node.program.interpreter, node);
  }

  this.print(node.program, node);
}

function Program(node) {
  this.printInnerComments(node, false);
  this.printSequence(node.directives, node);
  if (node.directives && node.directives.length) this.newline();
  this.printSequence(node.body, node);
}

function BlockStatement(node) {
  this.token("{");
  this.printInnerComments(node);
  const hasDirectives = node.directives && node.directives.length;

  if (node.body.length || hasDirectives) {
    this.newline();
    this.printSequence(node.directives, node, {
      indent: true
    });
    if (hasDirectives) this.newline();
    this.printSequence(node.body, node, {
      indent: true
    });
    this.removeTrailingNewline();
    this.source("end", node.loc);
    if (!this.endsWith("\n")) this.newline();
    this.rightBrace();
  } else {
    this.source("end", node.loc);
    this.token("}");
  }
}

function Noop() {}

function Directive(node) {
  this.print(node.value, node);
  this.semicolon();
}

const unescapedSingleQuoteRE = /(?:^|[^\\])(?:\\\\)*'/;
const unescapedDoubleQuoteRE = /(?:^|[^\\])(?:\\\\)*"/;

function DirectiveLiteral(node) {
  const raw = this.getPossibleRaw(node);

  if (raw != null) {
    this.token(raw);
    return;
  }

  const {
    value
  } = node;

  if (!unescapedDoubleQuoteRE.test(value)) {
    this.token(`"${value}"`);
  } else if (!unescapedSingleQuoteRE.test(value)) {
    this.token(`'${value}'`);
  } else {
    throw new Error("Malformed AST: it is not possible to print a directive containing" + " both unescaped single and double quotes.");
  }
}

function InterpreterDirective(node) {
  this.token(`#!${node.value}\n`);
}

function Placeholder(node) {
  this.token("%%");
  this.print(node.name);
  this.token("%%");

  if (node.expectedNode === "Statement") {
    this.semicolon();
  }
}