/*
 * 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.xml.util;

import com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor;
import com.intellij.lang.Language;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.UserDataCache;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.IdReferenceProvider;
import com.intellij.psi.impl.source.xml.PossiblePrefixReference;
import com.intellij.psi.impl.source.xml.SchemaPrefix;
import com.intellij.psi.impl.source.xml.SchemaPrefixReference;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.*;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.xml.XmlAttributeDescriptor;
import com.intellij.xml.XmlElementDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * @author spleaner
 */
public class XmlRefCountHolder {
  private static final Key<CachedValue<XmlRefCountHolder>> xmlRefCountHolderKey = Key.create("xml ref count holder");

  private static final UserDataCache<CachedValue<XmlRefCountHolder>, XmlFile, Object> CACHE =
    new UserDataCache<CachedValue<XmlRefCountHolder>, XmlFile, Object>() {
      @Override
      protected CachedValue<XmlRefCountHolder> compute(final XmlFile file, final Object p) {
        return CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<XmlRefCountHolder>() {
          @Override
          public Result<XmlRefCountHolder> compute() {
            final XmlRefCountHolder holder = new XmlRefCountHolder();
            final Language language = file.getViewProvider().getBaseLanguage();
            final PsiFile psiFile = file.getViewProvider().getPsi(language);
            assert psiFile != null;
            psiFile.accept(new IdGatheringRecursiveVisitor(holder));
            return new Result<XmlRefCountHolder>(holder, file);
          }
        }, false);
      }
    };

  private final Map<String, List<Pair<XmlAttributeValue, Boolean>>> myId2AttributeListMap = new HashMap<String, List<Pair<XmlAttributeValue, Boolean>>>();
  private final Set<XmlAttributeValue> myPossiblyDuplicateIds = new HashSet<XmlAttributeValue>();
  private final List<XmlAttributeValue> myIdReferences = new ArrayList<XmlAttributeValue>();
  private final Set<String> myAdditionallyDeclaredIds = new HashSet<String>();
  private final Set<PsiElement> myDoNotValidateParentsList = new HashSet<PsiElement>();
  private final Set<String> myUsedPrefixes = new HashSet<String>();
  private final Set<String> myUsedNamespaces = new HashSet<String>();

  @Nullable
  public static XmlRefCountHolder getRefCountHolder(final XmlElement element) {
    PsiFile file = element.getContainingFile();
    return file instanceof XmlFile ? CACHE.get(xmlRefCountHolderKey, (XmlFile)file, null).getValue() : null;
  }

  private XmlRefCountHolder() {
  }


  public boolean isDuplicateIdAttributeValue(@NotNull final XmlAttributeValue value) {
    return myPossiblyDuplicateIds.contains(value);
  }

  public boolean isValidatable(@Nullable final PsiElement element) {
    return !myDoNotValidateParentsList.contains(element);
  }

  public boolean hasIdDeclaration(@NotNull final String idRef) {
    return myId2AttributeListMap.get(idRef) != null || myAdditionallyDeclaredIds.contains(idRef);
  }

  public boolean isIdReferenceValue(@NotNull final XmlAttributeValue value) {
    return myIdReferences.contains(value);
  }

  private void registerId(@NotNull final String id, @NotNull final XmlAttributeValue attributeValue, final boolean soft) {
    List<Pair<XmlAttributeValue, Boolean>> list = myId2AttributeListMap.get(id);
    if (list == null) {
      list = new ArrayList<Pair<XmlAttributeValue, Boolean>>();
      myId2AttributeListMap.put(id, list);
    }
    else if (!soft) {
      final boolean html = HtmlUtil.isHtmlFile(attributeValue);
      final boolean html5 = HtmlUtil.isHtml5Context(attributeValue);

      // mark as duplicate
      List<XmlAttributeValue> notSoft = ContainerUtil.mapNotNull(list, new NullableFunction<Pair<XmlAttributeValue, Boolean>, XmlAttributeValue>() {
        @Override
        public XmlAttributeValue fun(Pair<XmlAttributeValue, Boolean> pair) {
          if (html5 && !"id".equalsIgnoreCase(((XmlAttribute)pair.first.getParent()).getName())) {
            // according to HTML 5 (http://www.w3.org/TR/html5/dom.html#the-id-attribute) spec
            // only id attribute is unique identifier
            return null;
          }
          if (html && pair.first.getParent().getParent() == attributeValue.getParent().getParent()) {
            // according to HTML 4 (http://www.w3.org/TR/html401/struct/global.html#adef-id,
            // http://www.w3.org/TR/html401/struct/links.html#h-12.2.3) spec id and name occupy
            // same namespace, but having same values on one tag is ok
            return null;
          }
          return pair.second ? null : pair.first;
        }
      });
      if (!notSoft.isEmpty()) {
        myPossiblyDuplicateIds.addAll(notSoft);
        myPossiblyDuplicateIds.add(attributeValue);
      }
    }

    list.add(new Pair<XmlAttributeValue, Boolean>(attributeValue, soft));
  }

  private void registerAdditionalId(@NotNull final String id) {
    myAdditionallyDeclaredIds.add(id);
  }

  private void registerIdReference(@NotNull final XmlAttributeValue value) {
    myIdReferences.add(value);
  }

  private void registerOuterLanguageElement(@NotNull final PsiElement element) {
    PsiElement parent = element.getParent();

    if (parent instanceof XmlText) {
      parent = parent.getParent();
    }

    myDoNotValidateParentsList.add(parent);
  }

  public boolean isInUse(String prefix) {
    return myUsedPrefixes.contains(prefix);
  }

  public boolean isUsedNamespace(String ns) {
    return myUsedNamespaces.contains(ns);
  }

  private static class IdGatheringRecursiveVisitor extends XmlRecursiveElementVisitor {
    private final XmlRefCountHolder myHolder;

    private IdGatheringRecursiveVisitor(@NotNull XmlRefCountHolder holder) {
      super(true);
      myHolder = holder;
    }

    @Override
    public void visitElement(final PsiElement element) {
      if (element instanceof OuterLanguageElement) {
        visitOuterLanguageElement(element);
      }

      super.visitElement(element);
    }

    private void visitOuterLanguageElement(@NotNull final PsiElement element) {
      myHolder.registerOuterLanguageElement(element);
      PsiReference[] references = element.getReferences();
      for (PsiReference reference : references) {
        if (reference instanceof PossiblePrefixReference && ((PossiblePrefixReference)reference).isPrefixReference()) {
          PsiElement resolve = reference.resolve();
          if (resolve instanceof SchemaPrefix) {
            myHolder.addUsedPrefix(((SchemaPrefix)resolve).getName());
          }
        }
      }
    }

    @Override
    public void visitComment(final PsiComment comment) {
      doVisitAnyComment(comment);
      super.visitComment(comment);
    }

    @Override
    public void visitXmlComment(final XmlComment comment) {
      doVisitAnyComment(comment);
      super.visitXmlComment(comment);
    }

    private void doVisitAnyComment(final PsiComment comment) {
      final String id = XmlDeclareIdInCommentAction.getImplicitlyDeclaredId(comment);
      if (id != null) {
        myHolder.registerAdditionalId(id);
      }
    }

    @Override
    public void visitXmlTag(XmlTag tag) {
      myHolder.addUsedPrefix(tag.getNamespacePrefix());
      myHolder.addUsedNamespace(tag.getNamespace());
      String text = tag.getValue().getTrimmedText();
      detectPrefix(text);
      super.visitXmlTag(tag);
    }

    @Override
    public void visitXmlAttribute(XmlAttribute attribute) {
      if (!attribute.isNamespaceDeclaration()) {
        myHolder.addUsedPrefix(attribute.getNamespacePrefix());
      }
      myHolder.addUsedNamespace(attribute.getNamespace());
      super.visitXmlAttribute(attribute);
    }

    @Override
    public void visitXmlAttributeValue(final XmlAttributeValue value) {
      final PsiElement element = value.getParent();
      if (!(element instanceof XmlAttribute)) return;

      final XmlAttribute attribute = (XmlAttribute)element;

      final XmlTag tag = attribute.getParent();
      if (tag == null) return;

      final XmlElementDescriptor descriptor = tag.getDescriptor();
      if (descriptor == null) return;

      final XmlAttributeDescriptor attributeDescriptor = descriptor.getAttributeDescriptor(attribute);
      if (attributeDescriptor != null) {
        if (attributeDescriptor.hasIdType()) {
          updateMap(attribute, value, false);
        }
        else {
          final PsiReference[] references = value.getReferences();
          for (PsiReference r : references) {
            if (r instanceof IdReferenceProvider.GlobalAttributeValueSelfReference /*&& !r.isSoft()*/) {
              updateMap(attribute, value, r.isSoft());
            }
            else if (r instanceof SchemaPrefixReference) {
              SchemaPrefix prefix = ((SchemaPrefixReference)r).resolve();
              if (prefix != null) {
                myHolder.addUsedPrefix(prefix.getName());
              }
            }
          }
        }

        if (attributeDescriptor.hasIdRefType() && PsiTreeUtil.getChildOfType(value, OuterLanguageElement.class) == null) {
          myHolder.registerIdReference(value);
        }
      }

      String s = value.getValue();
      detectPrefix(s);
      super.visitXmlAttributeValue(value);
    }

    private void detectPrefix(String s) {
      if (s != null) {
        int pos = s.indexOf(':');
        if (pos > 0) {
          myHolder.addUsedPrefix(s.substring(0, pos));
        }
      }
    }

    private void updateMap(@NotNull final XmlAttribute attribute, @NotNull final XmlAttributeValue value, final boolean soft) {
      final String id = XmlHighlightVisitor.getUnquotedValue(value, attribute.getParent());
      if (XmlUtil.isSimpleValue(id, value) &&
          PsiTreeUtil.getChildOfType(value, OuterLanguageElement.class) == null) {
        myHolder.registerId(id, value, soft);
      }
    }
  }

  private void addUsedPrefix(String prefix) {
    myUsedPrefixes.add(prefix);
  }

  private void addUsedNamespace(String ns) {
    myUsedNamespaces.add(ns);
  }
}
