// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a

class TagStack {
  List<ASTNode> _stack;

  TagStack(var elem) : _stack = [] {
    _stack.add(elem);
  }

  void push(var elem) {
    _stack.add(elem);
  }

  ASTNode pop() {
    return _stack.removeLast();
  }

  top() {
    return _stack.last;
  }
}

// TODO(terry): Cleanup returning errors from CSS to common World error
//              handler.
class ErrorMsgRedirector {
  void displayError(String msg) {
    if (world.printHandler != null) {
      world.printHandler(msg);
    } else {
      print("Unhandler Error: ${msg}");
    }
    world.errors++;
  }
}

/**
 * A simple recursive descent parser for HTML.
 */
class Parser {
  Tokenizer tokenizer;

  var _fs;                        // If non-null filesystem to read files.

  final SourceFile source;

  Token _previousToken;
  Token _peekToken;

  PrintHandler printHandler;

  Parser(this.source, [int start = 0, this._fs = null]) {
    tokenizer = new Tokenizer(source, true, start);
    _peekToken = tokenizer.next();
    _previousToken = null;
  }

  // Main entry point for parsing an entire HTML file.
  List<Template> parse([PrintHandler handler = null]) {
    printHandler = handler;

    List<Template> productions = [];

    int start = _peekToken.start;
    while (!_maybeEat(TokenKind.END_OF_FILE)) {
      Template template = processTemplate();
      if (template != null) {
        productions.add(template);
      }
    }

    return productions;
  }

  /** Generate an error if [source] has not been completely consumed. */
  void checkEndOfFile() {
    _eat(TokenKind.END_OF_FILE);
  }

  /** Guard to break out of parser when an unexpected end of file is found. */
  // TODO(jimhug): Failure to call this method can lead to inifinite parser
  //   loops.  Consider embracing exceptions for more errors to reduce
  //   the danger here.
  bool isPrematureEndOfFile() {
    if (_maybeEat(TokenKind.END_OF_FILE)) {
      _error('unexpected end of file', _peekToken.span);
      return true;
    } else {
      return false;
    }
  }

  ///////////////////////////////////////////////////////////////////
  // Basic support methods
  ///////////////////////////////////////////////////////////////////
  int _peek() {
    return _peekToken.kind;
  }

  Token _next([bool inTag = true]) {
    _previousToken = _peekToken;
    _peekToken = tokenizer.next(inTag);
    return _previousToken;
  }

  bool _peekKind(int kind) {
    return _peekToken.kind == kind;
  }

  /* Is the next token a legal identifier?  This includes pseudo-keywords. */
  bool _peekIdentifier([String name = null]) {
    if (TokenKind.isIdentifier(_peekToken.kind)) {
      return (name != null) ? _peekToken.text == name : true;
    }

    return false;
  }

  bool _maybeEat(int kind) {
    if (_peekToken.kind == kind) {
      _previousToken = _peekToken;
      if (kind == TokenKind.GREATER_THAN) {
        _peekToken = tokenizer.next(false);
      } else {
        _peekToken = tokenizer.next();
      }
      return true;
    } else {
      return false;
    }
  }

  void _eat(int kind) {
    if (!_maybeEat(kind)) {
      _errorExpected(TokenKind.kindToString(kind));
    }
  }

  void _eatSemicolon() {
    _eat(TokenKind.SEMICOLON);
  }

  void _errorExpected(String expected) {
    var tok = _next();
    var message;
    try {
      message = 'expected $expected, but found $tok';
    } catch (e) {
      message = 'parsing error expected $expected';
    }
    _error(message, tok.span);
  }

  void _error(String message, [SourceSpan location=null]) {
    if (location == null) {
      location = _peekToken.span;
    }

    if (printHandler == null) {
      world.fatal(message, location);    // syntax errors are fatal for now
    } else {
      // TODO(terry):  Need common World view for css and template parser.
      //               For now this is how we return errors from CSS - ugh.
      printHandler(message);
    }
  }

  void _warning(String message, [SourceSpan location=null]) {
    if (location == null) {
      location = _peekToken.span;
    }

    if (printHandler == null) {
      world.warning(message, location);
    } else {
      // TODO(terry):  Need common World view for css and template parser.
      //               For now this is how we return errors from CSS - ugh.
      printHandler(message);
    }
  }

  SourceSpan _makeSpan(int start) {
    return new SourceSpan(source, start, _previousToken.end);
  }

  ///////////////////////////////////////////////////////////////////
  // Top level productions
  ///////////////////////////////////////////////////////////////////

  Template processTemplate() {
    var template;

    int start = _peekToken.start;

    // Handle the template keyword followed by template signature.
    _eat(TokenKind.TEMPLATE_KEYWORD);

    if (_peekIdentifier()) {
      final templateName = identifier();

      List<Map<Identifier, Identifier>> params =
        new List<Map<Identifier, Identifier>>();

      _eat(TokenKind.LPAREN);

      start = _peekToken.start;
      while (true) {
        // TODO(terry): Need robust Dart argument parser (e.g.,
        //              List<String> arg1, etc).
        var type = processAsIdentifier();
        var paramName = processAsIdentifier();
        if (type != null && paramName != null) {
          params.add({'type': type, 'name' : paramName});

          if (!_maybeEat(TokenKind.COMMA)) {
            break;
          }
        } else {
          // No parameters we're done.
          break;
        }
      }

      _eat(TokenKind.RPAREN);

      TemplateSignature sig =
        new TemplateSignature(templateName.name, params, _makeSpan(start));

      TemplateContent content = processTemplateContent();

      template = new Template(sig, content, _makeSpan(start));
    }

    return template;
  }

  // All tokens are identifiers tokenizer is geared to HTML if identifiers are
  // HTML element or attribute names we need them as an identifier.  Used by
  // template signatures and expressions in ${...}
  Identifier processAsIdentifier() {
    int start = _peekToken.start;

    if (_peekIdentifier()) {
      return identifier();
    } else if (TokenKind.validTagName(_peek())) {
      var tok = _next();
      return new Identifier(TokenKind.tagNameFromTokenId(tok.kind),
        _makeSpan(start));
    }
  }

  css.Stylesheet processCSS() {
    // Is there a CSS block?
    if (_peekIdentifier('css')) {
      _next();

      int start = _peekToken.start;
      _eat(TokenKind.LBRACE);

      css.Stylesheet cssCtx = processCSSContent(source, tokenizer.startIndex);

      // TODO(terry): Hack, restart template parser where CSS parser stopped.
      tokenizer.index = lastCSSIndexParsed;
     _next(false);

      _eat(TokenKind.RBRACE);       // close } of css block

      return cssCtx;
    }
  }

  // TODO(terry): get should be able to use all template control flow but return
  //              a string instead of a node.  Maybe expose both html and get
  //              e.g.,
  //
  //              A.)
  //              html {
  //                <div>...</div>
  //              }
  //
  //              B.)
  //              html foo() {
  //                <div>..</div>
  //              }
  //
  //              C.)
  //              get {
  //                <div>...</div>
  //              }
  //
  //              D.)
  //              get foo {
  //                <div>..</div>
  //              }
  //
  //              Only one default allower either A or C the constructor will
  //              generate a string or a node.
  //              Examples B and D would generate getters that either return
  //              a node for B or a String for D.
  //
  List<TemplateGetter> processGetters() {
    List<TemplateGetter> getters = [];

    while (true) {
      if (_peekIdentifier('get')) {
        _next();

        int start = _peekToken.start;
        if (_peekIdentifier()) {
          String getterName = identifier().name;

          List<Map<Identifier, Identifier>> params =
            new List<Map<Identifier, Identifier>>();

          _eat(TokenKind.LPAREN);

          start = _peekToken.start;
          while (true) {
            // TODO(terry): Need robust Dart argument parser (e.g.,
            //              List<String> arg1, etc).
            var type = processAsIdentifier();
            var paramName = processAsIdentifier();
            if (paramName == null && type != null) {
              paramName = type;
              type = "";
            }
            if (type != null && paramName != null) {
              params.add({'type': type, 'name' : paramName});

              if (!_maybeEat(TokenKind.COMMA)) {
                break;
              }
            } else {
              // No parameters we're done.
              break;
            }
          }

          _eat(TokenKind.RPAREN);

          _eat(TokenKind.LBRACE);

          var elems = new TemplateElement.fragment(_makeSpan(_peekToken.start));
          var templateDoc = processHTML(elems);

          _eat(TokenKind.RBRACE);       // close } of get block

          getters.add(new TemplateGetter(getterName, params, templateDoc,
            _makeSpan(_peekToken.start)));
        }
      } else {
        break;
      }
    }

    return getters;

/*
    get newTotal(value) {
      <div class="alignleft">${value}</div>
    }

    String get HTML_newTotal(value) {
      return '<div class="alignleft">${value}</div>
    }

*/
  }

  TemplateContent processTemplateContent() {
    css.Stylesheet ss;

    _eat(TokenKind.LBRACE);

    int start = _peekToken.start;

    ss = processCSS();

    // TODO(terry): getters should be allowed anywhere not just after CSS.
    List<TemplateGetter> getters = processGetters();

    var elems = new TemplateElement.fragment(_makeSpan(_peekToken.start));
    var templateDoc = processHTML(elems);

    // TODO(terry): Should allow css { } to be at beginning or end of the
    //              template's content.  Today css only allow at beginning
    //              because the css {...} is sucked in as a text node.  We'll
    //              need a special escape for css maybe:
    //
    //                  ${#css}
    //                  ${/css}
    //
    //              uggggly!


    _eat(TokenKind.RBRACE);

    return new TemplateContent(ss, templateDoc, getters, _makeSpan(start));
  }

  int lastCSSIndexParsed;       // TODO(terry): Hack, last good CSS parsed.

  css.Stylesheet processCSSContent(var cssSource, int start) {
    try {
      css.Parser parser = new css.Parser(new SourceFile(
          SourceFile.IN_MEMORY_FILE, cssSource.text), start);

      css.Stylesheet stylesheet = parser.parse(false, new ErrorMsgRedirector());

      var lastParsedChar = parser.tokenizer.startIndex;

      lastCSSIndexParsed = lastParsedChar;

      return stylesheet;
    } catch (cssParseException) {
      // TODO(terry): Need SourceSpan from CSS parser to pass onto _error.
      _error("Unexcepted CSS error: ${cssParseException.toString()}");
    }
  }

  /* TODO(terry): Assume template {   },  single close curley as a text node
   *              inside of the template would need to be escaped maybe \}
   */
  processHTML(TemplateElement root) {
    assert(root.isFragment);
    TagStack stack = new TagStack(root);

    int start = _peekToken.start;

    bool done = false;
    while (!done) {
      if (_maybeEat(TokenKind.LESS_THAN)) {
        // Open tag
        start = _peekToken.start;

        if (TokenKind.validTagName(_peek())) {
          Token tagToken = _next();

          Map<String, TemplateAttribute> attrs = processAttributes();

          String varName;
          if (attrs.containsKey('var')) {
            varName = attrs['var'].value;
            attrs.remove('var');
          }

          int scopeType;     // 1 implies scoped, 2 implies non-scoped element.
          if (_maybeEat(TokenKind.GREATER_THAN)) {
            // Scoped unless the tag is explicitly known as an unscoped tag
            // e.g., <br>.
            scopeType = TokenKind.unscopedTag(tagToken.kind) ? 2 : 1;
          } else if (_maybeEat(TokenKind.END_NO_SCOPE_TAG)) {
            scopeType = 2;
          }
          if (scopeType > 0) {
            var elem = new TemplateElement.attributes(tagToken.kind,
              attrs.values.toList(), varName, _makeSpan(start));
            stack.top().add(elem);

            if (scopeType == 1) {
              // Maybe more nested tags/text?
              stack.push(elem);
            }
          }
        } else {
          // Close tag
          _eat(TokenKind.SLASH);
          if (TokenKind.validTagName(_peek())) {
            Token tagToken = _next();

            _eat(TokenKind.GREATER_THAN);

            var elem = stack.pop();
            if (elem is TemplateElement && !elem.isFragment) {
              if (elem.tagTokenId != tagToken.kind) {
                _error('Tag doesn\'t match expected </${elem.tagName}> got ' +
                  '</${TokenKind.tagNameFromTokenId(tagToken.kind)}>');
              }
            } else {
              // Too many end tags.
              _error('Too many end tags at ' +
                  '</${TokenKind.tagNameFromTokenId(tagToken.kind)}>');
            }
          }
        }
      } else if (_maybeEat(TokenKind.START_COMMAND)) {
        Identifier commandName = processAsIdentifier();
        if (commandName != null) {
          switch (commandName.name) {
            case "each":
            case "with":
              var listName = processAsIdentifier();
              if (listName != null) {
                var loopItem = processAsIdentifier();
                // Is the optional item name specified?
                //    #each lists [item]
                //    #with expression [item]

                _eat(TokenKind.RBRACE);

                var frag = new TemplateElement.fragment(
                    _makeSpan(_peekToken.start));
                TemplateDocument docFrag = processHTML(frag);

                if (docFrag != null) {
                  var span = _makeSpan(start);
                  var cmd;
                  if (commandName.name == "each") {
                    cmd = new TemplateEachCommand(listName, loopItem, docFrag,
                        span);
                  } else if (commandName.name == "with") {
                    cmd = new TemplateWithCommand(listName, loopItem, docFrag,
                        span);
                  }

                  stack.top().add(cmd);
                  stack.push(cmd);
                }

                // Process ${/commandName}
                _eat(TokenKind.END_COMMAND);

                // Close command ${/commandName}
                if (_peekIdentifier()) {
                  commandName = identifier();
                  switch (commandName.name) {
                    case "each":
                    case "with":
                    case "if":
                    case "else":
                      break;
                    default:
                      _error('Unknown command \${#${commandName}}');
                  }
                  var elem = stack.pop();
                  if (elem is TemplateEachCommand &&
                      commandName.name == "each") {

                  } else if (elem is TemplateWithCommand &&
                    commandName.name == "with") {

                  } /*else if (elem is TemplateIfCommand && commandName == "if") {

                  }
                  */else {
                    String expectedCmd;
                    if (elem is TemplateEachCommand) {
                      expectedCmd = "\${/each}";
                    } /* TODO(terry): else other commands as well */
                    _error('mismatched command expected ${expectedCmd} got...');
                    return;
                  }
                  _eat(TokenKind.RBRACE);
                } else {
                  _error('Missing command name \${/commandName}');
                }
              } else {
                _error("Missing listname for #each command");
              }
              break;
            case "if":
              break;
            case "else":
              break;
            default:
              // Calling another template.
              int startPos = this._previousToken.end;
              // Gobble up everything until we hit }
              while (_peek() != TokenKind.RBRACE &&
                     _peek() != TokenKind.END_OF_FILE) {
                _next(false);
              }

              if (_peek() == TokenKind.RBRACE) {
                int endPos = this._previousToken.end;
                TemplateCall callNode = new TemplateCall(commandName.name,
                    source.text.substring(startPos, endPos), _makeSpan(start));
                stack.top().add(callNode);

                _next(false);
              } else {
                _error("Unknown template command");
              }
          }  // End of switch/case
        }
      } else if (_peekKind(TokenKind.END_COMMAND)) {
        break;
      } else {
        // Any text or expression nodes?
        var nodes = processTextNodes();
        if (nodes.length > 0) {
          assert(stack.top() != null);
          for (var node in nodes) {
            stack.top().add(node);
          }
        } else {
          break;
        }
      }
    }
/*
    if (elems.children.length != 1) {
      print("ERROR: No closing end-tag for elems ${elems[elems.length - 1]}");
    }
*/
    var docChildren = new List<ASTNode>();
    docChildren.add(stack.pop());
    return new TemplateDocument(docChildren, _makeSpan(start));
  }

  /* Map is used so only last unique attribute name is remembered and to quickly
   * find the var attribute.
   */
  Map<String, TemplateAttribute> processAttributes() {
    Map<String, TemplateAttribute> attrs = new Map();

    int start = _peekToken.start;
    String elemName;
    while (_peekIdentifier() ||
           (elemName = TokenKind.tagNameFromTokenId(_peek())) != null) {
      var attrName;
      if (elemName == null) {
        attrName = identifier();
      } else {
        attrName = new Identifier(elemName, _makeSpan(start));
        _next();
      }

      var attrValue;

      // Attribute value?
      if (_peek() == TokenKind.ATTR_VALUE) {
        var tok = _next();
        attrValue = new StringValue(tok.value, _makeSpan(tok.start));
      }

      attrs[attrName.name] =
        new TemplateAttribute(attrName, attrValue, _makeSpan(start));

      start = _peekToken.start;
      elemName = null;
    }

    return attrs;
  }

  identifier() {
    var tok = _next();
    if (!TokenKind.isIdentifier(tok.kind)) {
      _error('expected identifier, but found $tok', tok.span);
    }

    return new Identifier(tok.text, _makeSpan(tok.start));
  }

  List<ASTNode> processTextNodes() {
    // May contain TemplateText and TemplateExpression.
    List<ASTNode> nodes = [];

    int start = _peekToken.start;
    bool inExpression = false;
    StringBuffer stringValue = new StringBuffer();

    // Any text chars between close of tag and text node?
    if (_previousToken.kind == TokenKind.GREATER_THAN) {
      // If the next token is } could be the close template token.  If user
      // needs } as token in text node use the entity &125;
      // TODO(terry): Probably need a &RCURLY entity instead of 125.
      if (_peek() == TokenKind.ERROR) {
        // Backup, just past previous token, & rescan we're outside of the tag.
        tokenizer.index = _previousToken.end;
        _next(false);
      } else if (_peek() != TokenKind.RBRACE) {
        // Yes, grab the chars after the >
        stringValue.write(_previousToken.source.text.substring(
            this._previousToken.end, this._peekToken.start));
      }
    }

    // Gobble up everything until we hit <
    while (_peek() != TokenKind.LESS_THAN &&
           _peek() != TokenKind.START_COMMAND &&
           _peek() != TokenKind.END_COMMAND &&
           (_peek() != TokenKind.RBRACE ||
            (_peek() == TokenKind.RBRACE && inExpression)) &&
           _peek() != TokenKind.END_OF_FILE) {

      // Beginning of expression?
      if (_peek() == TokenKind.START_EXPRESSION) {
        if (stringValue.length > 0) {
          // We have a real text node create the text node.
          nodes.add(new TemplateText(stringValue.toString(), _makeSpan(start)));
          stringValue = new StringBuffer();
          start = _peekToken.start;
        }
        inExpression = true;
      }

      var tok = _next(false);
      if (tok.kind == TokenKind.RBRACE && inExpression) {
        // We have an expression create the expression node, don't save the }
        inExpression = false;
        nodes.add(new TemplateExpression(stringValue.toString(),
          _makeSpan(start)));
        stringValue = new StringBuffer();
        start = _peekToken.start;
      } else if (tok.kind != TokenKind.START_EXPRESSION) {
        // Only save the the contents between ${ and }
        stringValue.write(tok.text);
      }
    }

    if (stringValue.length > 0) {
      nodes.add(new TemplateText(stringValue.toString(), _makeSpan(start)));
    }

    return nodes;
  }

}