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, newline) {
      var out = "";

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

      out = out + string;

      if(newline !== false) { out = out + "\n"; }
      return out;
    };

    PrintVisitor.prototype.program = function(program) {
      var out = "",
          statements = program.statements,
          i, l;

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

      this.padding--;

      return out;
    };

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

      out = out + this.pad("BLOCK:");
      this.padding++;
      out = out + this.accept(block.mustache);
      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.sexpr = 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.id) + " " + params + hash;
    };

    PrintVisitor.prototype.mustache = function(mustache) {
      return this.pad("{{ " + this.accept(mustache.sexpr) + " }}");
    };

    PrintVisitor.prototype.partial = function(partial) {
      var content = this.accept(partial.partialName);
      if(partial.context) { content = content + " " + this.accept(partial.context); }
      return this.pad("{{> " + content + " }}");
    };

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

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

      return "HASH{" + joinedPairs.join(", ") + "}";
    };

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

    PrintVisitor.prototype.INTEGER = function(integer) {
      return "INTEGER{" + integer.integer + "}";
    };

    PrintVisitor.prototype.BOOLEAN = function(bool) {
      return "BOOLEAN{" + bool.bool + "}";
    };

    PrintVisitor.prototype.ID = function(id) {
      var path = id.parts.join("/");
      if(id.parts.length > 1) {
        return "PATH:" + path;
      } else {
        return "ID:" + path;
      }
    };

    PrintVisitor.prototype.PARTIAL_NAME = function(partialName) {
        return "PARTIAL:" + partialName.name;
    };

    PrintVisitor.prototype.DATA = function(data) {
      return "@" + this.accept(data.id);
    };

    PrintVisitor.prototype.content = function(content) {
      return this.pad("CONTENT[ '" + content.string + "' ]");
    };

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