/*
 * Copyright 2007 Sascha Weinreuter
 *
 * 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 org.intellij.lang.xpath.xslt.impl;

import com.intellij.lang.ASTNode;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.injection.MultiHostInjector;
import com.intellij.lang.injection.MultiHostRegistrar;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.xml.XmlAttributeValueImpl;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlElementType;
import com.intellij.util.SmartList;
import org.intellij.lang.xpath.XPathTokenTypes;
import org.intellij.lang.xpath.xslt.XsltSupport;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Arrays;
import java.util.List;

public class XPathLanguageInjector implements MultiHostInjector {
    private static final Key<Pair<String, TextRange[]>> CACHED_FILES = Key.create("CACHED_FILES");
    private static final TextRange[] EMPTY_ARRAY = new TextRange[0];

    public XPathLanguageInjector() {
    }

    @Nullable
    private static TextRange[] getCachedRanges(XmlAttribute attribute) {
        Pair<String, TextRange[]> pair;
        if ((pair = attribute.getUserData(CACHED_FILES)) != null) {
            if (!attribute.getValue().equals(pair.getFirst())) {
                attribute.putUserData(CACHED_FILES, null);
                return null;
            }
        } else {
            return null;
        }
        return pair.getSecond();
    }

    static final class AVTRange extends TextRange {
        final boolean myComplete;

        private AVTRange(int startOffset, int endOffset, boolean iscomplete) {
            super(startOffset, endOffset);
            myComplete = iscomplete;
        }

        public static AVTRange create(XmlAttribute attribute, int startOffset, int endOffset, boolean iscomplete) {
            return new AVTRange(attribute.displayToPhysical(startOffset), attribute.displayToPhysical(endOffset), iscomplete);
        }
    }

    @NotNull
    private synchronized TextRange[] getInjectionRanges(final XmlAttribute attribute, XsltChecker.LanguageLevel languageLevel) {
      final TextRange[] cachedFiles = getCachedRanges(attribute);
      if (cachedFiles != null) {
        return cachedFiles;
      }

      final String value = attribute.getDisplayValue();
      if (value == null) return EMPTY_ARRAY;

      final TextRange[] ranges;
      if (XsltSupport.mayBeAVT(attribute)) {
        final List<TextRange> avtRanges = new SmartList<TextRange>();

        int i;
        int j = 0;
        Lexer lexer = null;
        while ((i = XsltSupport.getAVTOffset(value, j)) != -1) {
          if (lexer == null) {
            lexer = LanguageParserDefinitions.INSTANCE.forLanguage(languageLevel.getXPathVersion().getLanguage())
              .createLexer(attribute.getProject());
          }

          // "A right curly brace inside a Literal in an expression is not recognized as terminating the expression."
          lexer.start(value, i, value.length());
          j = -1;
          while (lexer.getTokenType() != null) {
            if (lexer.getTokenType() == XPathTokenTypes.RBRACE) {
              j = lexer.getTokenStart();
              break;
            }
            lexer.advance();
          }

          if (j != -1) {
            avtRanges.add(AVTRange.create(attribute, i, j + 1, j > i + 1));
          } else {
            // missing '}' error will be flagged by xpath parser
            avtRanges.add(AVTRange.create(attribute, i, value.length(), false));
            break;
          }
        }

        if (avtRanges.size() > 0) {
          ranges = avtRanges.toArray(new TextRange[avtRanges.size()]);
        } else {
          ranges = EMPTY_ARRAY;
        }
      } else {
        ranges = new TextRange[]{ attribute.getValueTextRange() };
      }

      attribute.putUserData(CACHED_FILES, Pair.create(attribute.getValue(), ranges));

      return ranges;
    }

  @NotNull
  public List<? extends Class<? extends PsiElement>> elementsToInjectIn() {
    return Arrays.asList(XmlAttribute.class);
  }

  public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
    final XmlAttribute attribute = (XmlAttribute)context;
    if (!XsltSupport.isXPathAttribute(attribute)) return;

    XmlAttributeValueImpl value = (XmlAttributeValueImpl)attribute.getValueElement();
    if (value == null) return;
    ASTNode type = value.findChildByType(XmlElementType.XML_ENTITY_REF);
    if (type != null) return; // workaround for inability to inject into text with entity refs (e.g. IDEA-72972) TODO: fix it

    final XsltChecker.LanguageLevel languageLevel = XsltSupport.getXsltLanguageLevel(attribute.getContainingFile());
    final TextRange[] ranges = getInjectionRanges(attribute, languageLevel);
    for (TextRange range : ranges) {
      // workaround for http://www.jetbrains.net/jira/browse/IDEA-10096
      TextRange rangeInsideHost;
      String prefix;
      if (range instanceof AVTRange) {
        if (((AVTRange)range).myComplete) {
          rangeInsideHost = range.shiftRight(2).grown(-2);
          prefix = "";
        }
        else {
          // we need to keep the "'}' expected" parse error
          rangeInsideHost = range.shiftRight(2).grown(-1);
          prefix = "{";
        }
      }
      else {
        rangeInsideHost = range;
        prefix = "";
      }
      if (value.getTextRange().contains(rangeInsideHost.shiftRight(value.getTextRange().getStartOffset()))) {
        registrar.startInjecting(languageLevel.getXPathVersion().getLanguage())
                .addPlace(prefix, "", value, rangeInsideHost)
                .doneInjecting();
      }
    }
  }
}
