/*
 * Copyright 2000-2013 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * @author max
 */
package com.intellij.psi.impl.source.parsing.xml;

import com.intellij.lang.*;
import com.intellij.lang.impl.PsiBuilderImpl;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.xml.XmlElementType;
import com.intellij.psi.xml.XmlTokenType;
import com.intellij.util.containers.Stack;
import com.intellij.util.diff.FlyweightCapableTreeStructure;
import com.intellij.xml.util.XmlUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

public class XmlBuilderDriver {
  private final Stack<String> myNamespacesStack = new Stack<String>();
  private final Stack<String> myPrefixesStack = new Stack<String>();
  private final CharSequence myText;
  @NonNls private static final String XMLNS = "xmlns";
  @NonNls private static final String XMLNS_COLON = "xmlns:";

  public XmlBuilderDriver(final CharSequence text) {
    myText = text;
  }

  protected CharSequence getText() {
    return myText;
  }

  public void addImplicitBinding(@NonNls @NotNull String prefix, @NonNls @NotNull String namespace) {
    myNamespacesStack.push(namespace);
    myPrefixesStack.push(prefix);
  }

  public void build(XmlBuilder builder) {
    PsiBuilder b = createBuilderAndParse();

    FlyweightCapableTreeStructure<LighterASTNode> structure = b.getLightTree();

    LighterASTNode root = structure.getRoot();
    root = structure.prepareForGetChildren(root);

    final Ref<LighterASTNode[]> childrenRef = Ref.create(null);
    final int count = structure.getChildren(root, childrenRef);
    LighterASTNode[] children = childrenRef.get();

    for (int i = 0; i < count; i++) {
      LighterASTNode child = children[i];
      final IElementType tt = child.getTokenType();
      if (tt == XmlElementType.XML_TAG || tt == XmlElementType.HTML_TAG) {
        processTagNode(b, structure, child, builder);
      }
      else if (tt == XmlElementType.XML_PROLOG) {
        processPrologNode(b, builder, structure, child);
      }
    }

    structure.disposeChildren(children, count);
  }

  private void processPrologNode(PsiBuilder psiBuilder,
                                 XmlBuilder builder,
                                 FlyweightCapableTreeStructure<LighterASTNode> structure,
                                 LighterASTNode prolog) {
    final Ref<LighterASTNode[]> prologChildren = new Ref<LighterASTNode[]>(null);
    final int prologChildrenCount = structure.getChildren(structure.prepareForGetChildren(prolog), prologChildren);
    for (int i = 0; i < prologChildrenCount; i++) {
      LighterASTNode node = prologChildren.get()[i];
      IElementType type = node.getTokenType();
      if (type == XmlElementType.XML_DOCTYPE) {
        processDoctypeNode(builder, structure, node);
        break;
      }
      if (type == TokenType.ERROR_ELEMENT) {
        processErrorNode(psiBuilder, node, builder);
      }
    }
  }

  private void processDoctypeNode(final XmlBuilder builder, final FlyweightCapableTreeStructure<LighterASTNode> structure,
                                  final LighterASTNode doctype) {
    final Ref<LighterASTNode[]> tokens = new Ref<LighterASTNode[]>(null);
    final int tokenCount = structure.getChildren(structure.prepareForGetChildren(doctype), tokens);
    if (tokenCount > 0) {
      CharSequence publicId = null;
      boolean afterPublic = false;
      CharSequence systemId = null;
      boolean afterSystem = false;
      for (int i = 0; i < tokenCount; i++) {
        LighterASTNode token = tokens.get()[i];
        if (token.getTokenType() == XmlTokenType.XML_DOCTYPE_PUBLIC) {
          afterPublic = true;
        }
        else if (token.getTokenType() == XmlTokenType.XML_DOCTYPE_SYSTEM) {
          afterSystem = true;
        }
        else if (token.getTokenType() != TokenType.WHITE_SPACE && token.getTokenType() != XmlElementType.XML_COMMENT) {
          if (token.getTokenType() == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) {
            if (afterPublic) publicId = getTokenText(token);
            else if (afterSystem) systemId = getTokenText(token);
          }
          afterPublic = afterSystem = false;
        }
      }
      builder.doctype(publicId, systemId, doctype.getStartOffset(), doctype.getEndOffset());
    }
  }

  private CharSequence getTokenText(final LighterASTNode token) {
    return myText.subSequence(token.getStartOffset(), token.getEndOffset());
  }

  protected PsiBuilder createBuilderAndParse() {
    final ParserDefinition xmlParserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(XMLLanguage.INSTANCE);
    assert xmlParserDefinition != null;

    PsiBuilder b = PsiBuilderFactory.getInstance().createBuilder(xmlParserDefinition, xmlParserDefinition.createLexer(null), myText);
    new XmlParsing(b).parseDocument();
    return b;
  }

  private void processErrorNode(PsiBuilder psiBuilder, LighterASTNode node, XmlBuilder builder) {
    assert node.getTokenType() == TokenType.ERROR_ELEMENT;
    String message = PsiBuilderImpl.getErrorMessage(node);
    assert message != null;
    builder.error(message, node.getStartOffset(), node.getEndOffset());
  }

  private void processTagNode(PsiBuilder psiBuilder,
                              FlyweightCapableTreeStructure<LighterASTNode> structure,
                              LighterASTNode node,
                              XmlBuilder builder) {
    final IElementType nodeTT = node.getTokenType();
    assert nodeTT == XmlElementType.XML_TAG || nodeTT == XmlElementType.HTML_TAG;

    node = structure.prepareForGetChildren(node);

    final Ref<LighterASTNode[]> childrenRef = Ref.create(null);
    final int count = structure.getChildren(node, childrenRef);
    LighterASTNode[] children = childrenRef.get();

    int stackFrameSize = myNamespacesStack.size();
    CharSequence tagName = "";
    int headerEndOffset = node.getEndOffset();
    for (int i = 0; i < count; i++) {
      LighterASTNode child = children[i];
      final IElementType tt = child.getTokenType();
      if (tt == XmlElementType.XML_ATTRIBUTE) checkForXmlns(child, structure);
      if (tt == XmlTokenType.XML_TAG_END || tt == XmlTokenType.XML_EMPTY_ELEMENT_END) {
        headerEndOffset = child.getEndOffset();
        break;
      }
      if (tt == XmlTokenType.XML_NAME || tt == XmlTokenType.XML_TAG_NAME) {
        tagName = getTokenText(child);
      }
    }

    CharSequence localName = XmlUtil.getLocalName(tagName);
    String namespace = getNamespace(tagName);

    XmlBuilder.ProcessingOrder order = builder.startTag(localName, namespace, node.getStartOffset(), node.getEndOffset(), headerEndOffset);
    boolean processAttrs = order == XmlBuilder.ProcessingOrder.TAGS_AND_ATTRIBUTES ||
                           order == XmlBuilder.ProcessingOrder.TAGS_AND_ATTRIBUTES_AND_TEXTS;

    boolean processTexts = order == XmlBuilder.ProcessingOrder.TAGS_AND_TEXTS ||
                           order == XmlBuilder.ProcessingOrder.TAGS_AND_ATTRIBUTES_AND_TEXTS;

    for (int i = 0; i < count; i++) {
      LighterASTNode child = children[i];
      IElementType tt = child.getTokenType();
      if (tt == TokenType.ERROR_ELEMENT) processErrorNode(psiBuilder, child, builder);
      if (tt == XmlElementType.XML_TAG || tt == XmlElementType.HTML_TAG) processTagNode(psiBuilder, structure, child, builder);
      if (processAttrs && tt == XmlElementType.XML_ATTRIBUTE) processAttributeNode(child, structure, builder);
      if (processTexts && tt == XmlElementType.XML_TEXT) processTextNode(structure, child, builder);
      if (tt == XmlElementType.XML_ENTITY_REF) builder.entityRef(getTokenText(child), child.getStartOffset(), child.getEndOffset());
    }

    builder.endTag(localName, namespace, node.getStartOffset(), node.getEndOffset());

    int framesToDrop = myNamespacesStack.size() - stackFrameSize;
    for (int i = 0; i < framesToDrop; i++) {
      myNamespacesStack.pop();
      myPrefixesStack.pop();
    }

    structure.disposeChildren(children, count);
  }

  private void processTextNode(FlyweightCapableTreeStructure<LighterASTNode> structure, LighterASTNode node, XmlBuilder builder) {
    node = structure.prepareForGetChildren(node);

    final Ref<LighterASTNode[]> childrenRef = Ref.create(null);
    final int count = structure.getChildren(node, childrenRef);
    LighterASTNode[] children = childrenRef.get();

    for (int i = 0; i < count; i++) {
      LighterASTNode child = children[i];
      IElementType tt = child.getTokenType();
      final int start = child.getStartOffset();
      final int end = child.getEndOffset();
      final CharSequence physical = getTokenText(child);

      if (XmlTokenType.COMMENTS.contains(tt)) continue;

      if (tt == XmlTokenType.XML_CDATA_START || tt == XmlTokenType.XML_CDATA_END) {
        builder.textElement("", physical, start, end);
      }
      else if (tt == XmlElementType.XML_CDATA) {
        processTextNode(structure, child, builder);
      }
      else if (tt == XmlTokenType.XML_CHAR_ENTITY_REF) {
        builder.textElement(new String(new char[] {XmlUtil.getCharFromEntityRef(physical.toString())}), physical, start, end);
      }
      else {
        builder.textElement(physical, physical, start, end);
      }
    }

    structure.disposeChildren(children, count);
  }

  private void processAttributeNode(final LighterASTNode attrNode, FlyweightCapableTreeStructure<LighterASTNode> structure, XmlBuilder builder) {
    builder.attribute(getAttributeName(attrNode, structure), getAttributeValue(attrNode, structure), attrNode.getStartOffset(), attrNode.getEndOffset());
  }

  private String getNamespace(final CharSequence tagName) {
    final String namespacePrefix;
    int pos = StringUtil.indexOf(tagName, ':');
    if (pos == -1) {
      namespacePrefix = "";
    }
    else {
      namespacePrefix = tagName.subSequence(0, pos).toString();
    }

    for (int i = myPrefixesStack.size() - 1; i >= 0; i--) {
      if (namespacePrefix.equals(myPrefixesStack.get(i))) return myNamespacesStack.get(i);
    }

    return "";
  }

  private void checkForXmlns(LighterASTNode attrNode, FlyweightCapableTreeStructure<LighterASTNode> structure) {
    final CharSequence name = getAttributeName(attrNode, structure);
    if (Comparing.equal(name, XMLNS)) {
      myPrefixesStack.push("");
      myNamespacesStack.push(getAttributeValue(attrNode, structure).toString());
    }
    else if (StringUtil.startsWith(name, XMLNS_COLON)) {
      myPrefixesStack.push(name.subSequence(XMLNS_COLON.length(), name.length()).toString());
      myNamespacesStack.push(getAttributeValue(attrNode, structure).toString());
    }
  }


  private CharSequence getAttributeName(LighterASTNode attrNode, FlyweightCapableTreeStructure<LighterASTNode> structure) {
    return findTextByTokenType(attrNode, structure, XmlTokenType.XML_NAME);
  }

  private CharSequence getAttributeValue(LighterASTNode attrNode, FlyweightCapableTreeStructure<LighterASTNode> structure) {
    final CharSequence fullValue = findTextByTokenType(attrNode, structure, XmlElementType.XML_ATTRIBUTE_VALUE);
    int start = 0;
    if (fullValue.length() > 0 && fullValue.charAt(0) == '\"') start++;

    int end = fullValue.length();
    if (fullValue.length() > start && fullValue.charAt(fullValue.length() - 1) == '\"') end--;

    return fullValue.subSequence(start, end);
  }

  private CharSequence findTextByTokenType(LighterASTNode attrNode,
                                           FlyweightCapableTreeStructure<LighterASTNode> structure,
                                           IElementType tt) {
    attrNode = structure.prepareForGetChildren(attrNode);

    final Ref<LighterASTNode[]> childrenRef = Ref.create(null);
    final int count = structure.getChildren(attrNode, childrenRef);
    LighterASTNode[] children = childrenRef.get();

    CharSequence name = "";
    for (int i = 0; i < count; i++) {
      LighterASTNode child = children[i];
      if (child.getTokenType() == tt) {
        name = getTokenText(child);
        break;
      }
    }

    structure.disposeChildren(children, count);

    return name;
  }

}
