/*
 * Copyright 2000-2010 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.html.impl;

import com.intellij.html.index.Html5CustomAttributesIndex;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.xml.XmlAttributeDescriptor;
import com.intellij.xml.XmlAttributeDescriptorsProvider;
import com.intellij.xml.impl.schema.AnyXmlAttributeDescriptor;
import com.intellij.xml.util.HtmlUtil;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author Eugene.Kudelevsky
 */
public class Html5CustomAttributeDescriptorsProvider implements XmlAttributeDescriptorsProvider {
  @Override
  public XmlAttributeDescriptor[] getAttributeDescriptors(XmlTag tag) {
    if (tag == null || !HtmlUtil.isHtml5Context(tag)) {
      return XmlAttributeDescriptor.EMPTY;
    }
    final List<String> currentAttrs = new ArrayList<String>();
    for (XmlAttribute attribute : tag.getAttributes()) {
      currentAttrs.add(attribute.getName());
    }
    final List<XmlAttributeDescriptor> result = new ArrayList<XmlAttributeDescriptor>();
    final GlobalSearchScope scope = GlobalSearchScope.allScope(tag.getProject());
    final Collection<String> keys = FileBasedIndex.getInstance().getAllKeys(Html5CustomAttributesIndex.INDEX_ID, tag.getProject());
    for (String key : keys) {
      final boolean canProcessKey = !FileBasedIndex.getInstance().processValues(Html5CustomAttributesIndex.INDEX_ID, key,
                                                                                null, new FileBasedIndex.ValueProcessor<Void>() {
          @Override
          public boolean process(VirtualFile file, Void value) {
            return false;
          }
        }, scope);
      if (!canProcessKey) continue;

      boolean add = true;
      for (String attr : currentAttrs) {
        if (attr.startsWith(key)) {
          add = false;
        }
      }
      if (add) {
        result.add(new AnyXmlAttributeDescriptor(key));
      }
    }

    return result.toArray(new XmlAttributeDescriptor[result.size()]);
  }

  @Override
  public XmlAttributeDescriptor getAttributeDescriptor(String attributeName, XmlTag context) {
    if (context != null && HtmlUtil.isHtml5Context(context) && HtmlUtil.isCustomHtml5Attribute(attributeName)) {
      return new AnyXmlAttributeDescriptor(attributeName);
    }
    return null;
  }

}

@@ -718,73 +718,315 @@
 api.
-vfs.VirtualFile;%0Aimport com.intellij.psi.search.GlobalSearchScope
+project.Project;%0Aimport com.intellij.openapi.util.Condition;%0Aimport com.intellij.openapi.vfs.VirtualFile;%0Aimport com.intellij.psi.search.GlobalSearchScope;%0Aimport com.intellij.psi.util.CachedValueProvider;%0Aimport com.intellij.psi.util.CachedValuesManager;%0Aimport com.intellij.psi.util.PsiModificationTracker
 ;%0Aim
@@ -1101,16 +1101,67 @@
 XmlTag;%0A
+import com.intellij.util.containers.ContainerUtil;%0A
 import c
@@ -1408,16 +1408,59 @@
 tmlUtil;
+%0Aimport org.jetbrains.annotations.Nullable;
 %0A%0Aimport
@@ -2043,169 +2043,288 @@
 nal 
-List%3CXmlAttributeDescriptor%3E result = new ArrayList%3CXmlAttributeDescriptor%3E();%0A    final GlobalSearchScope scope = GlobalSearchScope.allScope(tag.getProject());%0A
+Project project = tag.getProject();%0A    final Collection%3CString%3E keys = CachedValuesManager.getManager(project).getCachedValue(project, new CachedValueProvider%3CCollection%3CString%3E%3E() %7B%0A        @Nullable%0A        @Override%0A        public Result%3CCollection%3CString%3E%3E compute() %7B%0A      
     
@@ -2436,92 +2436,290 @@
 ID, 
-tag.getP
+project);%0A          final GlobalSearchScope scope = GlobalSearchScope.allScope(p
 roject
-()
 );%0A    
+   
-for (String key : keys) %7B%0A      final boolean canProcessKey =
+   return Result.%3CCollection%3CString%3E%3Ecreate(ContainerUtil.filter(keys, new Condition%3CString%3E() %7B%0A            @Override%0A            public boolean value(String key) %7B%0A              return
  !Fi
@@ -2866,31 +2866,16 @@
         
-       
-        
 null, ne
@@ -2918,32 +2918,40 @@
 %3E() %7B%0A          
+      
+  
 @Override%0A      
@@ -2936,32 +2936,40 @@
       @Override%0A
+        
           public
@@ -3025,24 +3025,32 @@
             
+   
+     
 return false
@@ -3053,32 +3053,40 @@
 alse;%0A          
+        
 %7D%0A        %7D, sco
@@ -3079,16 +3079,24 @@
         
+ 
+       
 %7D, scope
@@ -3108,38 +3108,274 @@
     
-if (!canProcessKey) continue;%0A
+      %7D%0A          %7D), PsiModificationTracker.MODIFICATION_COUNT);%0A        %7D%0A      %7D);%0A    if (keys.isEmpty()) return XmlAttributeDescriptor.EMPTY;%0A%0A    final List%3CXmlAttributeDescriptor%3E result = new ArrayList%3CXmlAttributeDescriptor%3E();%0A    for (String key : keys) %7B
 %0A   

optimize custom attributes provider