/*
 * 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.
 */
package com.intellij.codeInsight.template.emmet.generators;

import com.intellij.codeInsight.template.CustomTemplateCallback;
import com.intellij.codeInsight.template.emmet.EmmetParser;
import com.intellij.codeInsight.template.emmet.XmlEmmetParser;
import com.intellij.codeInsight.template.emmet.ZenCodingTemplate;
import com.intellij.codeInsight.template.emmet.tokens.TemplateToken;
import com.intellij.codeInsight.template.emmet.tokens.ZenCodingToken;
import com.intellij.codeInsight.template.impl.TemplateImpl;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.options.UnnamedConfigurable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.xml.XmlTokenType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


/**
 * @author Eugene.Kudelevsky
 */
public abstract class ZenCodingGenerator {
  private static final ExtensionPointName<ZenCodingGenerator> EP_NAME =
    new ExtensionPointName<ZenCodingGenerator>("com.intellij.xml.zenCodingGenerator");
  private static final TokenSet VALID_LEAF_TYPES = TokenSet.create(XmlTokenType.XML_DATA_CHARACTERS, XmlTokenType.XML_CHAR_ENTITY_REF);

  public abstract TemplateImpl generateTemplate(@NotNull TemplateToken token, boolean hasChildren, @NotNull PsiElement context);

  @Nullable
  public TemplateImpl createTemplateByKey(@NotNull String key) {
    return null;
  }

  public abstract boolean isMyContext(@NotNull PsiElement context, boolean wrapping);

  @Nullable
  public String getSuffix() {
    return null;
  }

  public abstract boolean isAppliedByDefault(@NotNull PsiElement context);
  
  public abstract boolean isEnabled();

  public static List<ZenCodingGenerator> getInstances() {
    List<ZenCodingGenerator> generators = new ArrayList<ZenCodingGenerator>();
    Collections.addAll(generators, XmlZenCodingGeneratorImpl.INSTANCE);
    Collections.addAll(generators, EP_NAME.getExtensions());
    return generators;
  }

  @Nullable
  public String computeTemplateKey(@NotNull CustomTemplateCallback callback) {
    Editor editor = callback.getEditor();
    final int currentOffset = editor.getCaretModel().getOffset();
    final CharSequence documentText = editor.getDocument().getCharsSequence();
    PsiElement element = callback.getContext();
    int line = editor.getCaretModel().getLogicalPosition().line;
    int lineStart = editor.getDocument().getLineStartOffset(line);
    int elementStart = -1;
    do {
      PsiElement e = element;
      while ((e instanceof LeafPsiElement && VALID_LEAF_TYPES.contains(((LeafPsiElement)e).getElementType())) || 
             e instanceof PsiWhiteSpace || e instanceof PsiErrorElement) {
        elementStart = e.getTextRange().getStartOffset();
        e = e.getPrevSibling();
      }
      if (elementStart >= 0) {
        int startOffset = Math.max(elementStart, lineStart);
        String key = computeKey(startOffset, currentOffset, documentText);
        if (key != null) {
          while (key.length() > 0 && !ZenCodingTemplate.checkTemplateKey(key, callback, this)) {
            key = key.substring(1);
          }
          if (key.length() > 0) {
            return key;
          }
        }
      }
      element = element.getParent();
    }
    while (element != null && elementStart > lineStart);
    return null;
  }

  @Nullable
  protected static String computeKey(int startOffset, int currentOffset, CharSequence documentText) {
    if (currentOffset < startOffset || startOffset > documentText.length() || currentOffset > documentText.length()) {
      return null;
    }
    String s = documentText.subSequence(startOffset, currentOffset).toString();
    int index = 0;
    while (index < s.length() && Character.isWhitespace(s.charAt(index))) {
      index++;
    }
    String key = s.substring(index);
    int lastWhitespaceIndex = -1;
    int lastQuoteIndex = -1;
    int lastApostropheIndex = -1;
    boolean inBrackets = false;
    int bracesStack = 0;

    for (int i = 0; i < key.length(); i++) {
      char c = key.charAt(i);
      if (lastQuoteIndex >= 0 || lastApostropheIndex >= 0) {
        if (c == '"') {
          lastQuoteIndex = -1;
        }
        else if (c == '\'') lastApostropheIndex = -1;
      }
      else if (Character.isWhitespace(c)) {
        lastWhitespaceIndex = i;
      }
      else if (c == '"') {
        lastQuoteIndex = i;
      }
      else if (c == '\'') {
        lastApostropheIndex = i;
      }
      else if (c == '[') {
        inBrackets = true;
      }
      else if (c == ']' && inBrackets) {
        lastWhitespaceIndex = -1;
        inBrackets = false;
      }
      else if (c == '{') {
        bracesStack++;
      }
      else if (c == '}' && bracesStack > 0) {
        bracesStack--;
        if (bracesStack == 0) {
          lastWhitespaceIndex = -1;
        }
      }
    }
    if (lastQuoteIndex >= 0 || lastApostropheIndex >= 0) {
      int max = Math.max(lastQuoteIndex, lastApostropheIndex);
      return max < key.length() - 1 ? key.substring(max) : null;
    }
    if (lastWhitespaceIndex >= 0 && lastWhitespaceIndex < key.length() - 1) {
      return key.substring(lastWhitespaceIndex + 1);
    }
    return key;
  }

  @NotNull
  public EmmetParser createParser(List<ZenCodingToken> tokens,
                                  CustomTemplateCallback callback,
                                  ZenCodingGenerator generator,
                                  boolean surroundWithTemplate) {
    return new XmlEmmetParser(tokens, callback, generator, surroundWithTemplate);
  }
  
  @Nullable
  public UnnamedConfigurable createConfigurable() {
    return null;
  }
}
