define(['exports', './visitor'], function (exports, _visitor) {
  'use strict';

  var _interopRequire = function (obj) { return obj && obj.__esModule ? obj['default'] : obj; };

  exports.__esModule = true;
  exports.print = print;
  exports.PrintVisitor = PrintVisitor;
  /*eslint-disable new-cap */

  var _Visitor = _interopRequire(_visitor);

  function print(ast) {
    return new PrintVisitor().accept(ast);
  }

  function PrintVisitor() {
    this.padding = 0;
  }

  PrintVisitor.prototype = new _Visitor();

  PrintVisitor.prototype.pad = function (string) {
    var out = '';

    for (var i = 0, l = this.padding; i < l; i++) {
      out = out + '  ';
    }

    out = out + string + '\n';
    return out;
  };

  PrintVisitor.prototype.Program = function (program) {
    var out = '',
        body = program.body,
        i = undefined,
        l = undefined;

    if (program.blockParams) {
      var blockParams = 'BLOCK PARAMS: [';
      for (i = 0, l = program.blockParams.length; i < l; i++) {
        blockParams += ' ' + program.blockParams[i];
      }
      blockParams += ' ]';
      out += this.pad(blockParams);
    }

    for (i = 0, l = body.length; i < l; i++) {
      out = out + this.accept(body[i]);
    }

    this.padding--;

    return out;
  };

  PrintVisitor.prototype.MustacheStatement = function (mustache) {
    return this.pad('{{ ' + this.SubExpression(mustache) + ' }}');
  };

  PrintVisitor.prototype.BlockStatement = function (block) {
    var out = '';

    out = out + this.pad('BLOCK:');
    this.padding++;
    out = out + this.pad(this.SubExpression(block));
    if (block.program) {
      out = out + this.pad('PROGRAM:');
      this.padding++;
      out = out + this.accept(block.program);
      this.padding--;
    }
    if (block.inverse) {
      if (block.program) {
        this.padding++;
      }
      out = out + this.pad('{{^}}');
      this.padding++;
      out = out + this.accept(block.inverse);
      this.padding--;
      if (block.program) {
        this.padding--;
      }
    }
    this.padding--;

    return out;
  };

  PrintVisitor.prototype.PartialStatement = function (partial) {
    var content = 'PARTIAL:' + partial.name.original;
    if (partial.params[0]) {
      content += ' ' + this.accept(partial.params[0]);
    }
    if (partial.hash) {
      content += ' ' + this.accept(partial.hash);
    }
    return this.pad('{{> ' + content + ' }}');
  };

  PrintVisitor.prototype.ContentStatement = function (content) {
    return this.pad('CONTENT[ \'' + content.value + '\' ]');
  };

  PrintVisitor.prototype.CommentStatement = function (comment) {
    return this.pad('{{! \'' + comment.value + '\' }}');
  };

  PrintVisitor.prototype.SubExpression = function (sexpr) {
    var params = sexpr.params,
        paramStrings = [],
        hash = undefined;

    for (var i = 0, l = params.length; i < l; i++) {
      paramStrings.push(this.accept(params[i]));
    }

    params = '[' + paramStrings.join(', ') + ']';

    hash = sexpr.hash ? ' ' + this.accept(sexpr.hash) : '';

    return this.accept(sexpr.path) + ' ' + params + hash;
  };

  PrintVisitor.prototype.PathExpression = function (id) {
    var path = id.parts.join('/');
    return (id.data ? '@' : '') + 'PATH:' + path;
  };

  PrintVisitor.prototype.StringLiteral = function (string) {
    return '"' + string.value + '"';
  };

  PrintVisitor.prototype.NumberLiteral = function (number) {
    return 'NUMBER{' + number.value + '}';
  };

  PrintVisitor.prototype.BooleanLiteral = function (bool) {
    return 'BOOLEAN{' + bool.value + '}';
  };

  PrintVisitor.prototype.UndefinedLiteral = function () {
    return 'UNDEFINED';
  };

  PrintVisitor.prototype.NullLiteral = function () {
    return 'NULL';
  };

  PrintVisitor.prototype.Hash = function (hash) {
    var pairs = hash.pairs,
        joinedPairs = [];

    for (var i = 0, l = pairs.length; i < l; i++) {
      joinedPairs.push(this.accept(pairs[i]));
    }

    return 'HASH{' + joinedPairs.join(', ') + '}';
  };
  PrintVisitor.prototype.HashPair = function (pair) {
    return pair.key + '=' + this.accept(pair.value);
  };
  /*eslint-enable new-cap */
});