/*
 * Copyright 2005 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.references;

import com.intellij.codeInsight.completion.CompletionInitializationContext;
import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.LocalQuickFixProvider;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.xml.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import org.intellij.lang.xpath.completion.NamespaceLookup;
import org.intellij.lang.xpath.psi.impl.ResolveUtil;
import org.intellij.lang.xpath.xslt.XsltSupport;
import org.intellij.lang.xpath.xslt.context.XsltNamespaceContext;
import org.intellij.lang.xpath.xslt.impl.XsltChecker;
import org.intellij.lang.xpath.xslt.psi.impl.ImplicitModeElement;
import org.intellij.lang.xpath.xslt.util.MatchTemplateMatcher;
import org.intellij.lang.xpath.xslt.util.QNameUtil;
import org.intellij.lang.xpath.xslt.util.XsltCodeInsightUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.xml.namespace.QName;
import java.util.*;

class ModeReference extends SimpleAttributeReference implements PsiPolyVariantReference, EmptyResolveMessageProvider {
  private final boolean myIsDeclaration;
  private final ImplicitModeElement myImplicitModeElement;

  public ModeReference(XmlAttribute attribute, boolean isDeclaration) {
    super(attribute);
    if (isDeclaration) {
      myIsDeclaration = true;
    }
    else {
      final PsiFile file = attribute.getContainingFile();
      if (file != null && XsltSupport.getXsltLanguageLevel(file) == XsltChecker.LanguageLevel.V2) {
        final String value = attribute.getValue();
        myIsDeclaration = "#current".equals(value) || "#default".equals(value);
      }
      else {
        myIsDeclaration = false;
      }
    }
    myImplicitModeElement = new ImplicitModeElement(attribute);
  }

  @Override
  @NotNull
  protected TextRange getTextRange() {
    return myImplicitModeElement.getModeRange();
  }

  @NotNull
  public Object[] getVariants() {
    final PsiFile containingFile = myAttribute.getContainingFile();
    if (containingFile instanceof XmlFile && XsltSupport.isXsltFile(containingFile)) {
      final List<Object> l = new ArrayList<Object>();
      if (!myImplicitModeElement.hasPrefix()) {
        final Object[] prefixes = getPrefixCompletions(myAttribute);
        ContainerUtil.addAll(l, prefixes);
      }

      if (myImplicitModeElement.getQName() != null) {
        final PsiElement[] modes = ResolveUtil.collect(getMatcher().variantMatcher());
        ContainerUtil.addAll(l, modes);
      }
      return ArrayUtil.toObjectArray(l);
    }
    return ArrayUtil.EMPTY_OBJECT_ARRAY;
  }

  public boolean isSoft() {
    return myIsDeclaration;
  }

  @Override
  @Nullable
  public PsiElement resolveImpl() {
    if (myIsDeclaration) {
      return myImplicitModeElement;
    }
    else {
      final ResolveResult[] results = multiResolve(false);
      return results.length == 1 ? results[0].getElement() : null;
    }
  }

  @NotNull
  public ResolveResult[] multiResolve(final boolean incompleteCode) {
    final PsiFile containingFile = myAttribute.getContainingFile();
    if (containingFile instanceof XmlFile && XsltSupport.isXsltFile(containingFile) && myImplicitModeElement.getQName() != null) {
      return PsiElementResolveResult.createResults(ResolveUtil.collect(getMatcher()));
    }
    return ResolveResult.EMPTY_ARRAY;
  }

  private MyModeMatcher getMatcher() {
    return new MyModeMatcher(myAttribute, myImplicitModeElement.getQName());
  }

  public static PsiReference[] create(XmlAttribute attribute, boolean isDeclaration) {
    final String value = attribute.getValue();
    if (value == null) {
      return PsiReference.EMPTY_ARRAY;
    }
    if (value.trim().indexOf(' ') != -1) {
      // TODO: fix for xslt 2.0
      return PsiReference.EMPTY_ARRAY;
    }
    return createImpl(attribute, isDeclaration, value);
  }

  private static PsiReference[] createImpl(XmlAttribute attribute, boolean isDeclaration, String value) {
    final int p = value.indexOf(':');
    if (p == -1) {
      return new PsiReference[]{new ModeReference(attribute, isDeclaration)};
    }
    else if (p == value.length() - 1) {
      return new PsiReference[]{new MyPrefixReference(attribute)};
    }
    else {
      return new PsiReference[]{
        new MyPrefixReference(attribute),
        new ModeReference(attribute, isDeclaration)
      };
    }
  }

  static Object[] getPrefixCompletions(XmlAttribute attribute) {
    final ModeReference.MyModeMatcher matcher = new ModeReference.MyModeMatcher(attribute, QNameUtil.ANY);
    final PsiElement[] modes = ResolveUtil.collect(matcher);
    final Collection<String> prefixes = XsltNamespaceContext.getPrefixes(attribute);
    final Set<NamespaceLookup> lookups = new HashSet<NamespaceLookup>(prefixes.size());

    for (PsiElement mode : modes) {
      final QName qName = ((ImplicitModeElement)mode).getQName();
      if (qName == null) continue;
      final String prefix = qName.getPrefix();
      if (!prefixes.contains(prefix)) continue;

      lookups.add(new NamespaceLookup(prefix));
    }

    return ArrayUtil.toObjectArray(lookups);
  }

  private static class MyModeMatcher extends MatchTemplateMatcher {
    public MyModeMatcher(XmlDocument document, QName mode) {
      super(document, mode);
    }

    public MyModeMatcher(XmlElement element, QName mode) {
      super(XsltCodeInsightUtil.getDocument(element), mode);
    }

    protected PsiElement transform(XmlTag element) {
      return new ImplicitModeElement(element.getAttribute("mode", null));
    }

    public boolean matches(XmlTag element) {
      final String s = element.getAttributeValue("mode");
      return myMode != null &&
             s != null && s.indexOf(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED) == -1 &&
             super.matches(element);
    }

    @Override
    protected ResolveUtil.Matcher changeDocument(XmlDocument document) {
      return new MyModeMatcher(document, myMode);
    }

    public ResolveUtil.Matcher variantMatcher() {
      return new MyModeMatcher(myDocument, myMode != null ? QNameUtil.createAnyLocalName(myMode.getNamespaceURI()) : null);
    }
  }

  @NotNull
  public String getUnresolvedMessagePattern() {
    final QName qName = myImplicitModeElement.getQName();
    if (qName != null && qName != QNameUtil.UNRESOLVED) {
      return "Undefined mode '" + qName.toString() + "'";
    }
    else {
      return "Undefined mode ''{0}''";
    }
  }

  private static class MyPrefixReference extends PrefixReference implements LocalQuickFixProvider {
    public MyPrefixReference(XmlAttribute attribute) {
      super(attribute);
    }

    @Nullable
    @Override
    public LocalQuickFix[] getQuickFixes() {
      // TODO: This should actually scan all (reachable) xslt files for mode-declarations with the same local name
      return LocalQuickFix.EMPTY_ARRAY;
    }

    @NotNull
    @Override
    public Object[] getVariants() {
      return getPrefixCompletions(myAttribute);
    }
  }
}
