define(
  ["./visitor","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var Visitor = __dependency1__["default"];

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

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

    __exports__.PrintVisitor = PrintVisitor;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, l;

      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;

      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.Hash = function(hash) {
      var pairs = hash.pairs;
      var 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);
    };
  });