/*
 * Copyright 2000-2014 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.impl.schema;

import com.intellij.codeInsight.daemon.Validator;
import com.intellij.javaee.ExternalResourceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.meta.PsiMetaData;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.xml.XmlAttributeDescriptor;
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.XmlNSDescriptor;
import com.intellij.xml.XmlNSDescriptorEx;
import com.intellij.xml.impl.ExternalDocumentValidator;
import com.intellij.xml.util.XmlUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * @author Mike
 */
@SuppressWarnings({"HardCodedStringLiteral"})
public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator<XmlDocument>, DumbAware, XmlNSTypeDescriptorProvider {
  @NonNls
  public static final String XSD_PREFIX = "xsd";
  @NonNls public static final String SCHEMA_TAG_NAME = "schema";
  @NonNls public static final String IMPORT_TAG_NAME = "import";
  @NonNls static final String ELEMENT_TAG_NAME = "element";
  @NonNls static final String ATTRIBUTE_TAG_NAME = "attribute";
  @NonNls static final String COMPLEX_TYPE_TAG_NAME = "complexType";
  @NonNls static final String SEQUENCE_TAG_NAME = "sequence";
  private static final Logger LOG = Logger.getInstance("#com.intellij.xml.impl.schema.XmlNSDescriptorImpl");
  @NonNls private static final Set<String> STD_TYPES = new HashSet<String>();
  private static final Set<String> UNDECLARED_STD_TYPES = new HashSet<String>();
  @NonNls private static final String INCLUDE_TAG_NAME = "include";
  @NonNls private static final String REDEFINE_TAG_NAME = "redefine";
  private static final ThreadLocal<Set<PsiFile>> myRedefinedDescriptorsInProcessing = new ThreadLocal<Set<PsiFile>>();
  private final Map<QNameKey, CachedValue<XmlElementDescriptor>> myDescriptorsMap = Collections.synchronizedMap(new HashMap<QNameKey, CachedValue<XmlElementDescriptor>>());
  private final Map<Pair<QNameKey, XmlTag>, CachedValue<TypeDescriptor>> myTypesMap = Collections.synchronizedMap(new HashMap<Pair<QNameKey,XmlTag>, CachedValue<TypeDescriptor>>());
  private XmlFile myFile;
  private XmlTag myTag;
  private String myTargetNamespace;
  private volatile Object[] dependencies;
  private MultiMap<String,XmlTag> mySubstitutions;

  public XmlNSDescriptorImpl(XmlFile file) {
    init(file.getDocument());
  }

  public XmlNSDescriptorImpl() {
  }

  private static void collectDependencies(@Nullable XmlTag myTag, @NotNull XmlFile myFile, @NotNull Set<PsiFile> visited) {
    if (visited.contains(myFile)) return;
    visited.add( myFile );

    if (myTag == null) return;
    XmlTag[] tags = myTag.getSubTags();

    for (final XmlTag tag : tags) {
      if (equalsToSchemaName(tag, INCLUDE_TAG_NAME) ||
          equalsToSchemaName(tag, IMPORT_TAG_NAME)
        ) {
        final String schemaLocation = tag.getAttributeValue("schemaLocation");
        if (schemaLocation != null) {
          final XmlFile xmlFile = XmlUtil.findNamespace(myFile, schemaLocation);
          addDependency(xmlFile, visited);
        }
      } else if (equalsToSchemaName(tag, REDEFINE_TAG_NAME)) {
        myRedefinedDescriptorsInProcessing.set(visited);
        try {
          final XmlFile file = getRedefinedElementDescriptorFile(tag);
          addDependency(file, visited);
        } finally {
          myRedefinedDescriptorsInProcessing.set(null);
        }
      }
    }

    final String schemaLocationDeclaration = myTag.getAttributeValue("schemaLocation", XmlUtil.XML_SCHEMA_INSTANCE_URI);
    if(schemaLocationDeclaration != null) {
      final StringTokenizer tokenizer = new StringTokenizer(schemaLocationDeclaration);

      while(tokenizer.hasMoreTokens()){
        final String uri = tokenizer.nextToken();

        if(tokenizer.hasMoreTokens()){
          PsiFile resourceLocation = ExternalResourceManager.getInstance().getResourceLocation(tokenizer.nextToken(), myFile, null);
          if (resourceLocation == null) resourceLocation = ExternalResourceManager.getInstance().getResourceLocation(uri, myFile, null);

          if (resourceLocation instanceof XmlFile) addDependency((XmlFile)resourceLocation, visited);
        }
      }
    }
  }

  private static void addDependency(final XmlFile file, final Set<PsiFile> visited) {
    if (file != null) {
      final XmlDocument document = file.getDocument();
      collectDependencies(document != null ? document.getRootTag():null, file, visited);
    }
  }

  private static boolean checkSchemaNamespace(String name, XmlTag context){
    final String namespace = context.getNamespaceByPrefix(XmlUtil.findPrefixByQualifiedName(name));
    if(namespace.length() > 0){
      return checkSchemaNamespace(namespace);
    }
    return XSD_PREFIX.equals(XmlUtil.findPrefixByQualifiedName(name));
  }

  public static boolean checkSchemaNamespace(String namespace) {
    return XmlUtil.XML_SCHEMA_URI.equals(namespace) ||
           XmlUtil.XML_SCHEMA_URI2.equals(namespace) ||
           XmlUtil.XML_SCHEMA_URI3.equals(namespace);
  }

  public static boolean checkSchemaNamespace(XmlTag context) {
    LOG.assertTrue(context.isValid());
    final String namespace = context.getNamespace();
    if (namespace.length() > 0) {
      return checkSchemaNamespace(namespace);
    }
    return StringUtil.startsWithConcatenation(context.getName(), XSD_PREFIX, ":");
  }

  static @NotNull XmlNSDescriptorImpl getNSDescriptorToSearchIn(XmlTag rootTag, final String name, XmlNSDescriptorImpl defaultNSDescriptor) {
    if (name == null) return defaultNSDescriptor;
    final String namespacePrefix = XmlUtil.findPrefixByQualifiedName(name);

    if (namespacePrefix.length() > 0) {
      final String namespace = rootTag.getNamespaceByPrefix(namespacePrefix);
      final XmlNSDescriptor nsDescriptor = rootTag.getNSDescriptor(namespace, true);

      if (nsDescriptor instanceof XmlNSDescriptorImpl) {
        return (XmlNSDescriptorImpl)nsDescriptor;
      }
    }

    return defaultNSDescriptor;
  }

  @Nullable
  private static XmlElementDescriptor getDescriptorFromParent(final XmlTag tag, XmlElementDescriptor elementDescriptor) {
    final PsiElement parent = tag.getParent();
    if (parent instanceof XmlTag) {
      final XmlElementDescriptor descriptor = ((XmlTag)parent).getDescriptor();
      if (descriptor != null) elementDescriptor = descriptor.getElementDescriptor(tag, (XmlTag)parent);
    }
    return elementDescriptor;
  }

  public static boolean processTagsInNamespace(@NotNull final XmlTag rootTag, String[] tagNames, PsiElementProcessor<XmlTag> processor) {
    return processTagsInNamespaceInner(rootTag, tagNames, processor, null);
  }

  private static boolean processTagsInNamespaceInner(@NotNull final XmlTag rootTag, final String[] tagNames,
                                                     final PsiElementProcessor<XmlTag> processor, Set<XmlTag> visitedTags) {
    if (visitedTags == null) visitedTags = new HashSet<XmlTag>(3);
    else if (visitedTags.contains(rootTag)) return true;

    visitedTags.add(rootTag);
    XmlTag[] tags = rootTag.getSubTags();

    NextTag:
    for (XmlTag tag : tags) {
      for(String tagName:tagNames) {
        if (equalsToSchemaName(tag, tagName)) {
          final String name = tag.getAttributeValue("name");

          if (name != null) {
            if (!processor.execute(tag)) {
              return false;
            }
          }

          continue NextTag;
        }
      }

      if (equalsToSchemaName(tag, INCLUDE_TAG_NAME)) {
        final String schemaLocation = tag.getAttributeValue("schemaLocation");

        if (schemaLocation != null) {
          final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation);

          if (xmlFile != null) {
            final XmlDocument includedDocument = xmlFile.getDocument();

            if (includedDocument != null) {
              if (!processTagsInNamespaceInner(includedDocument.getRootTag(), tagNames, processor, visitedTags)) return false;
            }
          }
        }
      }
    }

    return true;
  }

  public static boolean equalsToSchemaName(@NotNull XmlTag tag, @NonNls String schemaName) {
    return schemaName.equals(tag.getLocalName()) && checkSchemaNamespace(tag);
  }

  private static @Nullable XmlTag findSpecialTag(@NonNls String name, @NonNls String specialName, XmlTag rootTag, XmlNSDescriptorImpl descriptor,
                                       HashSet<XmlTag> visited) {
    XmlNSDescriptorImpl nsDescriptor = getNSDescriptorToSearchIn(rootTag, name, descriptor);

    if (nsDescriptor != descriptor) {
      final XmlDocument document = nsDescriptor.getDescriptorFile() != null ? nsDescriptor.getDescriptorFile().getDocument():null;
      if (document == null) return null;

      return findSpecialTag(
        XmlUtil.findLocalNameByQualifiedName(name),
        specialName,
        document.getRootTag(),
        nsDescriptor,
        visited
      );
    }

    if (visited == null) visited = new HashSet<XmlTag>(1);
    else if (visited.contains(rootTag)) return null;
    visited.add(rootTag);

    XmlTag[] tags = rootTag.getSubTags();

    return findSpecialTagIn(tags, specialName, name, rootTag, descriptor, visited);
  }

  private static XmlTag findSpecialTagIn(final XmlTag[] tags,
                                         final String specialName,
                                         final String name,
                                         final XmlTag rootTag,
                                         final XmlNSDescriptorImpl descriptor, final HashSet<XmlTag> visited) {
    for (XmlTag tag : tags) {
      if (equalsToSchemaName(tag, specialName)) {
        String attribute = tag.getAttributeValue("name");

        if (name.equals(attribute)
            || name.contains(":") && name.substring(name.indexOf(":") + 1).equals(attribute)) {
          return tag;
        }
      } else if (equalsToSchemaName(tag, INCLUDE_TAG_NAME) ||
                 ( equalsToSchemaName(tag, IMPORT_TAG_NAME) &&
                   rootTag.getNamespaceByPrefix(
                     XmlUtil.findPrefixByQualifiedName(name)
                   ).equals(tag.getAttributeValue("namespace"))
                 )
         ) {
        final String schemaLocation = tag.getAttributeValue("schemaLocation");

        if (schemaLocation != null) {
          final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation);

          if (xmlFile != null) {
            final XmlDocument document = xmlFile.getDocument();
            if (document != null) {
              final XmlTag rTag = findSpecialTag(name, specialName, document.getRootTag(), descriptor, visited);

              if (rTag != null) return rTag;
            }
          }
        }
      } else if (equalsToSchemaName(tag, REDEFINE_TAG_NAME)) {
        XmlTag rTag = findSpecialTagIn(tag.getSubTags(), specialName, name, rootTag, descriptor, visited);
        if (rTag != null) return rTag;

        final XmlNSDescriptorImpl nsDescriptor = getRedefinedElementDescriptor(tag);
        if (nsDescriptor != null) {
          final XmlTag redefinedRootTag = ((XmlDocument)nsDescriptor.getDeclaration()).getRootTag();

          rTag = findSpecialTagIn(redefinedRootTag.getSubTags(), specialName, name, redefinedRootTag, nsDescriptor, visited);
          if (rTag != null) return rTag;
        }
      }
    }

    return null;
  }

  public static XmlNSDescriptorImpl getRedefinedElementDescriptor(final XmlTag parentTag) {
    XmlFile file = getRedefinedElementDescriptorFile(parentTag);
    if (file != null) {
      final XmlDocument document = file.getDocument();
      final PsiMetaData metaData = document != null ? document.getMetaData():null;
      if (metaData instanceof XmlNSDescriptorImpl) return (XmlNSDescriptorImpl)metaData;
    }
    return null;
  }

  public static XmlFile getRedefinedElementDescriptorFile(final XmlTag parentTag) {
    final String schemaL = parentTag.getAttributeValue(XmlUtil.SCHEMA_LOCATION_ATT);

    if (schemaL != null) {
      final PsiReference[] references = parentTag.getAttribute(XmlUtil.SCHEMA_LOCATION_ATT, null).getValueElement().getReferences();

      if (references.length > 0) {
        final PsiElement psiElement = references[references.length - 1].resolve();

        if (psiElement instanceof XmlFile) {
          return ((XmlFile)psiElement);
        }
      }
    }
    return null;
  }

  @Override
  public XmlFile getDescriptorFile() {
    return myFile;
  }

  @Override
  public boolean isHierarhyEnabled() {
    return true;
  }

  public String getDefaultNamespace(){
    return myTargetNamespace != null ? myTargetNamespace : "";
  }

  @Override
  @Nullable
  public XmlElementDescriptor getElementDescriptor(String localName, String namespace) {
    return getElementDescriptor(localName, namespace, new HashSet<XmlNSDescriptorImpl>(), false);
  }

  @Nullable
  public XmlElementDescriptor getElementDescriptor(String localName, String namespace, Set<XmlNSDescriptorImpl> visited, boolean reference) {
    if(visited.contains(this)) return null;

    final QNameKey pair = new QNameKey(namespace, localName);
    final CachedValue<XmlElementDescriptor> descriptor = myDescriptorsMap.get(pair);
    if(descriptor != null) {
      final XmlElementDescriptor value = descriptor.getValue();
      if (value == null || value.getDeclaration().isValid()) return value;
    }

    final XmlTag rootTag = myTag;
    if (rootTag == null) return null;
    XmlTag[] tags = rootTag.getSubTags();
    visited.add( this );

    LOG.assertTrue(rootTag.isValid());
    for (final XmlTag tag : tags) {
      if (equalsToSchemaName(tag, ELEMENT_TAG_NAME)) {
        String name = tag.getAttributeValue("name");

        if (name != null) {
          if (checkElementNameEquivalence(localName, namespace, name, tag)) {
            final CachedValue<XmlElementDescriptor> cachedValue = CachedValuesManager.getManager(tag.getProject()).createCachedValue(new CachedValueProvider<XmlElementDescriptor>() {
                @Override
                public Result<XmlElementDescriptor> compute() {
                  final String name = tag.getAttributeValue("name");

                  if (name != null && !name.equals(pair.second)) {
                    myDescriptorsMap.remove(pair);
                    return new Result<XmlElementDescriptor>(null, PsiModificationTracker.MODIFICATION_COUNT);
                  }
                  final XmlElementDescriptor xmlElementDescriptor = createElementDescriptor(tag);
                  return new Result<XmlElementDescriptor>(xmlElementDescriptor, xmlElementDescriptor.getDependences());
                }
              }, false);
            myDescriptorsMap.put(pair, cachedValue);
            return cachedValue.getValue();
          }
        }
      }
      else if (equalsToSchemaName(tag, INCLUDE_TAG_NAME) ||
               (reference &&
                equalsToSchemaName(tag, IMPORT_TAG_NAME) &&
                ( namespace.equals(tag.getAttributeValue("namespace")) ||
                  namespace.length() == 0 && tag.getAttributeValue("namespace") == null
                )
               )
        ) {
        final String schemaLocation = tag.getAttributeValue("schemaLocation");
        if (schemaLocation != null) {
          final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation);
          if (xmlFile != null) {
            final XmlDocument includedDocument = xmlFile.getDocument();
            if (includedDocument != null) {
              final PsiMetaData data = includedDocument.getMetaData();
              if (data instanceof XmlNSDescriptorImpl) {
                final XmlElementDescriptor elementDescriptor =
                  ((XmlNSDescriptorImpl)data).getElementDescriptor(localName, namespace, visited, reference);
                if (elementDescriptor != null) {
                  //final CachedValue<XmlElementDescriptor> value = includedDocument.getManager().getCachedValuesManager()
                  //  .createCachedValue(new CachedValueProvider<XmlElementDescriptor>() {
                  //    public Result<XmlElementDescriptor> compute() {
                  //      return new Result<XmlElementDescriptor>(elementDescriptor, elementDescriptor.getDependences());
                  //    }
                  //  }, false);
                  //return value.getValue();
                  return elementDescriptor;
                }
              }
            }
          }
        }
      } else if (equalsToSchemaName(tag, REDEFINE_TAG_NAME)) {
        final XmlNSDescriptorImpl nsDescriptor = getRedefinedElementDescriptor(tag);
        if (nsDescriptor != null) {
          final XmlElementDescriptor xmlElementDescriptor = nsDescriptor.getElementDescriptor(localName, namespace, visited, reference);
          if (xmlElementDescriptor instanceof XmlElementDescriptorImpl) {
            return new RedefinedElementDescriptor((XmlElementDescriptorImpl)xmlElementDescriptor, this);
          }
        }
      }
    }

    return null;
  }

  protected XmlElementDescriptor createElementDescriptor(final XmlTag tag) {
    return new XmlElementDescriptorImpl(tag);
  }

  private boolean checkElementNameEquivalence(String localName, String namespace, String fqn, XmlTag context){
    final String localAttrName = XmlUtil.findLocalNameByQualifiedName(fqn);
    if (!localAttrName.equals(localName)) return false;
    final String attrNamespace = context.getNamespaceByPrefix(XmlUtil.findPrefixByQualifiedName(fqn));
    if (attrNamespace.equals(namespace)) return true;

    if(myTargetNamespace == null){
      if(XmlUtil.EMPTY_URI.equals(attrNamespace))
        return true;
    }
    else {
      if (myTargetNamespace.equals(namespace)) return true;
      return context.getNSDescriptor(namespace, true) == this; // schema's targetNamespace could be different from file systemId
    }
    return false;
  }

  @Nullable
  public XmlAttributeDescriptor getAttribute(String localName, String namespace, final XmlTag context) {
    return getAttributeImpl(localName, namespace, null);
  }

  @Nullable
  private XmlAttributeDescriptor getAttributeImpl(String localName, String namespace, @Nullable Set<XmlTag> visited) {
    if (myTag == null) return null;

    XmlNSDescriptorImpl nsDescriptor = (XmlNSDescriptorImpl)myTag.getNSDescriptor(namespace, true);

    if (nsDescriptor != this && nsDescriptor != null) {
      return nsDescriptor.getAttributeImpl(
        localName,
        namespace,
        visited
      );
    }

    if (visited == null) visited = new HashSet<XmlTag>(1);
    else if(visited.contains(myTag)) return null;
    visited.add(myTag);
    XmlTag[] tags = myTag.getSubTags();

    for (XmlTag tag : tags) {
      if (equalsToSchemaName(tag, ATTRIBUTE_TAG_NAME)) {
        String name = tag.getAttributeValue("name");

        if (name != null) {
          if (checkElementNameEquivalence(localName, namespace, name, tag)) {
            return createAttributeDescriptor(tag);
          }
        }
      } else if (equalsToSchemaName(tag, INCLUDE_TAG_NAME) ||
                 (equalsToSchemaName(tag, IMPORT_TAG_NAME) &&
                  namespace.equals(tag.getAttributeValue("namespace"))
                 )
        ) {
        final String schemaLocation = tag.getAttributeValue("schemaLocation");

        if (schemaLocation != null) {
          final XmlFile xmlFile = XmlUtil.findNamespace(myTag.getContainingFile(), schemaLocation);

          if (xmlFile != null) {

            final XmlDocument includedDocument = xmlFile.getDocument();
            if (includedDocument != null) {
              final PsiMetaData data = includedDocument.getMetaData();

              if(data instanceof XmlNSDescriptorImpl){
                final XmlAttributeDescriptor attributeDescriptor = ((XmlNSDescriptorImpl)data).getAttributeImpl(localName, namespace,visited);

                if(attributeDescriptor != null){
                  final CachedValue<XmlAttributeDescriptor> value = CachedValuesManager.getManager(includedDocument.getProject()).createCachedValue(
                    new CachedValueProvider<XmlAttributeDescriptor>(){
                      @Override
                      public Result<XmlAttributeDescriptor> compute() {
                        Object[] deps = attributeDescriptor.getDependences();
                        if (deps.length == 0) {
                          LOG.error(attributeDescriptor + " returned no dependencies");
                        }
                        return new Result<XmlAttributeDescriptor>(attributeDescriptor, deps);
                      }
                    },
                    false
                  );
                  return value.getValue();
                }
              }
            }
          }
        }
      }
    }

    return null;
  }

  protected XmlAttributeDescriptorImpl createAttributeDescriptor(final XmlTag tag) {
    return new XmlAttributeDescriptorImpl(tag);
  }

  @Override
  public TypeDescriptor getTypeDescriptor(XmlTag descriptorTag) {
    String type = descriptorTag.getAttributeValue("type");

    if (type != null) {
      return getTypeDescriptor(type, descriptorTag);
    }

    return findTypeDescriptorImpl(descriptorTag, null, null, null);
  }

  @Override
  public TypeDescriptor getTypeDescriptor(final String name, XmlTag context) {
    if(checkSchemaNamespace(name, context)){
      final String localNameByQualifiedName = XmlUtil.findLocalNameByQualifiedName(name);

      if (STD_TYPES.contains(localNameByQualifiedName) &&
          ( name.length() == localNameByQualifiedName.length() ||
            UNDECLARED_STD_TYPES.contains(localNameByQualifiedName)
          )
         )
        return new StdTypeDescriptor(localNameByQualifiedName);
    }

    return findTypeDescriptor(name, context);
  }

  @Nullable
  public XmlElementDescriptor getDescriptorByType(String qName, XmlTag instanceTag){
    if(myTag == null) return null;
    final TypeDescriptor typeDescriptor = findTypeDescriptor(qName, instanceTag);
    if(!(typeDescriptor instanceof ComplexTypeDescriptor)) return null;
    return new XmlElementDescriptorByType(instanceTag, (ComplexTypeDescriptor)typeDescriptor);
  }

  @Nullable
  protected TypeDescriptor findTypeDescriptor(final String qname) {
    return findTypeDescriptor(qname, myTag);
  }

  @Nullable
  protected TypeDescriptor findTypeDescriptor(final String qname, XmlTag context) {
    String namespace = context.getNamespaceByPrefix(XmlUtil.findPrefixByQualifiedName(qname));
    return findTypeDescriptor(XmlUtil.findLocalNameByQualifiedName(qname), namespace);
  }

  @Nullable
  private TypeDescriptor findTypeDescriptor(String localName, String namespace) {
    return findTypeDescriptorImpl(myTag, localName, namespace, null);
  }

  @Nullable
  protected TypeDescriptor findTypeDescriptorImpl(XmlTag rootTag, final String name, String namespace, Set<XmlTag> visited) {
    XmlNSDescriptorImpl responsibleDescriptor = this;
    if (namespace != null && namespace.length() != 0 && !namespace.equals(getDefaultNamespace())) {
      final XmlNSDescriptor nsDescriptor = rootTag.getNSDescriptor(namespace, true);

      if (nsDescriptor instanceof XmlNSDescriptorImpl) {
        responsibleDescriptor = (XmlNSDescriptorImpl)nsDescriptor;
      }
    }

    if (responsibleDescriptor != this) {
      return responsibleDescriptor.findTypeDescriptor(XmlUtil.findLocalNameByQualifiedName(name));
    }

    if (rootTag == null) return null;
    if (visited != null) {
      if (visited.contains(rootTag)) return null;
      visited.add(rootTag);
    }

    final Pair<QNameKey, XmlTag> pair = Pair.create(new QNameKey(name, namespace), rootTag);

    final CachedValue<TypeDescriptor> descriptor = myTypesMap.get(pair);
    if(descriptor != null) {
      TypeDescriptor value = descriptor.getValue();
      if (value == null ||
          ( value instanceof ComplexTypeDescriptor &&
            ((ComplexTypeDescriptor)value).getDeclaration().isValid()
          )
         )
      return value;
    }

    XmlTag[] tags = rootTag.getSubTags();

    if (visited == null) {
      visited = new HashSet<XmlTag>(1);
      visited.add(rootTag);
    }

    return doFindIn(tags, name, namespace, pair, rootTag, visited);
  }

  private TypeDescriptor doFindIn(final XmlTag[] tags, final String name, final String namespace, final Pair<QNameKey, XmlTag> pair, final XmlTag rootTag, final Set<XmlTag> visited) {
    for (final XmlTag tag : tags) {
      if (equalsToSchemaName(tag, "complexType")) {
        if (name == null) {
          CachedValue<TypeDescriptor> value = createAndPutTypesCachedValue(tag, pair);
          return value.getValue();
        }

        String nameAttribute = tag.getAttributeValue("name");

        if (isSameName(name, namespace, nameAttribute)) {
          CachedValue<TypeDescriptor> cachedValue = createAndPutTypesCachedValue(tag, pair);
          return cachedValue.getValue();
        }
      }
      else if (equalsToSchemaName(tag, "simpleType")) {

        if (name == null) {
          CachedValue<TypeDescriptor> value = createAndPutTypesCachedValueSimpleType(tag, pair);
          return value.getValue();
        }

        String nameAttribute = tag.getAttributeValue("name");

        if (isSameName(name, namespace, nameAttribute)) {
          CachedValue<TypeDescriptor> cachedValue = createAndPutTypesCachedValue(tag, pair);
          return cachedValue.getValue();
        }
      }
      else if (equalsToSchemaName(tag, INCLUDE_TAG_NAME) ||
               ( equalsToSchemaName(tag, IMPORT_TAG_NAME) &&
                 (namespace == null || !namespace.equals(getDefaultNamespace()))
               )
              ) {
        final String schemaLocation = tag.getAttributeValue("schemaLocation");
        if (schemaLocation != null) {
          final XmlFile xmlFile = XmlUtil.findNamespace(rootTag.getContainingFile(), schemaLocation);

          if (xmlFile != null) {
            final XmlDocument document = xmlFile.getDocument();

            if (document != null) {

              final CachedValue<TypeDescriptor> value = CachedValuesManager.getManager(tag.getProject()).createCachedValue(new CachedValueProvider<TypeDescriptor>() {
                  @Override
                  public Result<TypeDescriptor> compute() {
                    final String currentName = tag.getAttributeValue("name");

                    if (( currentName != null &&
                          !currentName.equals(XmlUtil.findLocalNameByQualifiedName(name)) ) ||
                         !xmlFile.isValid() ||
                         xmlFile.getDocument() == null
                       ) {
                      myTypesMap.remove(pair);
                      return new Result<TypeDescriptor>(null, PsiModificationTracker.MODIFICATION_COUNT);
                    }

                    final XmlDocument document = xmlFile.getDocument();
                    final XmlNSDescriptorImpl nsDescriptor = findNSDescriptor(tag, document);

                    if (nsDescriptor == null) {
                      myTypesMap.remove(pair);
                      return new Result<TypeDescriptor>(null, PsiModificationTracker.MODIFICATION_COUNT);
                    }

                    final XmlTag rTag = document.getRootTag();

                    final TypeDescriptor complexTypeDescriptor = nsDescriptor.findTypeDescriptorImpl(rTag, name, namespace, visited);
                    return new Result<TypeDescriptor>(complexTypeDescriptor, rTag);
                  }
                }, false
              );

              if (value.getValue() != null) {
                myTypesMap.put(pair, value);
                return value.getValue();
              }
            }
          }
        }
      } else if (equalsToSchemaName(tag, REDEFINE_TAG_NAME)) {
        final XmlTag[] subTags = tag.getSubTags();
        TypeDescriptor descriptor = doFindIn(subTags, name, namespace, pair, rootTag, visited);
        if (descriptor != null) return descriptor;

        final XmlNSDescriptorImpl nsDescriptor = getRedefinedElementDescriptor(tag);
        if (nsDescriptor != null) {
          final XmlTag redefinedRootTag = ((XmlDocument)nsDescriptor.getDeclaration()).getRootTag();
          descriptor = doFindIn(redefinedRootTag.getSubTags(), name, namespace, pair, redefinedRootTag, visited);
          if (descriptor != null) return descriptor;
        }
      }
    }
    return null;
  }

  private boolean isSameName(@NotNull String name, String namespace, String nameAttribute) {
    return nameAttribute != null &&
           (nameAttribute.equals(name) || (name.contains(":") && nameAttribute.equals(name.substring(name.indexOf(":") + 1)))) &&
           (namespace == null || namespace.length() == 0 || namespace.equals(getDefaultNamespace()))
      ;
  }

  private XmlNSDescriptorImpl findNSDescriptor(final XmlTag tag, final XmlDocument document) {
    final XmlNSDescriptorImpl nsDescriptor;
    if(IMPORT_TAG_NAME.equals(tag.getLocalName())) {
      final XmlNSDescriptor importedDescriptor = (XmlNSDescriptor)document.getMetaData();
      nsDescriptor = (importedDescriptor instanceof XmlNSDescriptorImpl) ?
                     (XmlNSDescriptorImpl)importedDescriptor:
                     this;
    }
    else {
      nsDescriptor = this;
    }
    return nsDescriptor;
  }

  private CachedValue<TypeDescriptor> createAndPutTypesCachedValueSimpleType(final XmlTag tag, final Pair<QNameKey, XmlTag> pair) {
    final CachedValue<TypeDescriptor> value = CachedValuesManager.getManager(tag.getProject()).createCachedValue(new CachedValueProvider<TypeDescriptor>() {
      @Override
      public CachedValueProvider.Result<TypeDescriptor> compute() {
        final SimpleTypeDescriptor simpleTypeDescriptor = new SimpleTypeDescriptor(tag);
        return new Result<TypeDescriptor>(simpleTypeDescriptor, tag);
      }
    }, false);
    myTypesMap.put(pair, value);
    return value;
  }

  private CachedValue<TypeDescriptor> createAndPutTypesCachedValue(final XmlTag tag, final Pair<QNameKey, XmlTag> pair) {
    final CachedValue<TypeDescriptor> value = CachedValuesManager.getManager(tag.getProject()).createCachedValue(
      new CachedValueProvider<TypeDescriptor>() {
        @Override
        public CachedValueProvider.Result<TypeDescriptor> compute() {
          final String name = tag.getAttributeValue("name");

          if (name != null &&
              pair.first != null &&
              pair.first.first != null &&
              !name.equals(XmlUtil.findLocalNameByQualifiedName(pair.first.first))
            ) {
            myTypesMap.remove(pair);
            return new Result<TypeDescriptor>(null, PsiModificationTracker.MODIFICATION_COUNT);
          }
          final ComplexTypeDescriptor complexTypeDescriptor = new ComplexTypeDescriptor(XmlNSDescriptorImpl.this, tag);
          return new Result<TypeDescriptor>(complexTypeDescriptor, tag);
        }
      }, false);
    myTypesMap.put(pair, value);
    return value;
  }

  @Override
  public XmlElementDescriptor getElementDescriptor(@NotNull XmlTag tag) {
    PsiElement parent = tag.getParent();
    final String namespace = tag.getNamespace();
    while(parent instanceof XmlTag && !namespace.equals(((XmlTag)parent).getNamespace()))
      parent = parent.getContext();
    if (parent instanceof XmlTag) {
      final XmlTag parentTag = (XmlTag)parent;
      final XmlElementDescriptor parentDescriptor = parentTag.getDescriptor();

      if(parentDescriptor != null){
        XmlElementDescriptor elementDescriptorFromParent = parentDescriptor.getElementDescriptor(tag, parentTag);

        if (elementDescriptorFromParent == null) {
          elementDescriptorFromParent = getDescriptorFromParent(tag, elementDescriptorFromParent);
        }
        if (elementDescriptorFromParent instanceof AnyXmlElementDescriptor) {
          final XmlElementDescriptor elementDescriptor = getElementDescriptor(tag.getLocalName(), namespace);
          if (elementDescriptor != null) return elementDescriptor;
        }
        return elementDescriptorFromParent;
      }
      else{
        return null;
      }
    }
    else {
      XmlElementDescriptor elementDescriptor = getElementDescriptor(tag.getLocalName(), tag.getNamespace());

      if (elementDescriptor == null) {
        elementDescriptor = getDescriptorFromParent(tag, elementDescriptor);
      }

      return elementDescriptor;
    }
  }

  @Override
  @NotNull
  public XmlElementDescriptor[] getRootElementsDescriptors(@Nullable final XmlDocument doc) {
    class CollectElementsProcessor implements PsiElementProcessor<XmlTag> {
      final List<XmlElementDescriptor> result = new ArrayList<XmlElementDescriptor>();

      @Override
      public boolean execute(@NotNull final XmlTag element) {
        ContainerUtil.addIfNotNull(result, getElementDescriptor(element.getAttributeValue("name"), getDefaultNamespace()));
        return true;
      }
    }

    CollectElementsProcessor processor = new CollectElementsProcessor() {
      @Override
      public boolean execute(@NotNull final XmlTag element) {
        if (!XmlElementDescriptorImpl.isAbstractDeclaration(element)) return super.execute(element);
        return true;
      }
    };
    processTagsInNamespace(myTag, new String[] {ELEMENT_TAG_NAME}, processor);

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

  public XmlAttributeDescriptor[] getRootAttributeDescriptors(final XmlTag context) {
    class CollectAttributesProcessor implements PsiElementProcessor<XmlTag> {
      final List<XmlAttributeDescriptor> result = new ArrayList<XmlAttributeDescriptor>();

      @Override
      public boolean execute(@NotNull final XmlTag element) {
        result.add(createAttributeDescriptor(element));
        return true;
      }
    }

    CollectAttributesProcessor processor = new CollectAttributesProcessor();
    processTagsInNamespace(myTag, new String[] {ATTRIBUTE_TAG_NAME}, processor);

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

  @Nullable
  public XmlTag findGroup(String name) {
    return findSpecialTag(name,"group",myTag, this, null);
  }

  @Nullable
  public XmlTag findAttributeGroup(String name) {
    return findSpecialTag(name, "attributeGroup", myTag, this, null);
  }

  public XmlElementDescriptor[] getSubstitutes(String localName, String namespace) {
    if (!initSubstitutes()) {
      return XmlElementDescriptor.EMPTY_ARRAY;
    }
    Collection<XmlTag> substitutions = mySubstitutions.get(localName);
    if (substitutions.isEmpty()) return XmlElementDescriptor.EMPTY_ARRAY;
    List<XmlElementDescriptor> result = new SmartList<XmlElementDescriptor>();
    for (XmlTag tag : substitutions) {
      final String substAttr = tag.getAttributeValue("substitutionGroup");
      if (substAttr != null && checkElementNameEquivalence(localName, namespace, substAttr, tag)) {
        result.add(createElementDescriptor(tag));
      }
    }

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

  private boolean initSubstitutes() {
    if (mySubstitutions == null && myTag != null) {
      mySubstitutions = new MultiMap<String, XmlTag>();

      if (myTag == null) return false;

      XmlTag[] tags = myTag.getSubTags();

      for (XmlTag tag : tags) {
        if (equalsToSchemaName(tag, ELEMENT_TAG_NAME)) {
          final String substAttr = tag.getAttributeValue("substitutionGroup");
          if (substAttr != null) {
            String substLocalName = XmlUtil.findLocalNameByQualifiedName(substAttr);
            mySubstitutions.putValue(substLocalName, tag);
          }
        }
      }
    }
    return mySubstitutions != null;
  }

  @Override
  public PsiElement getDeclaration(){
    return myFile.getDocument();
  }

  @Override
  public String getName(PsiElement context){
    return getName();
  }

  @Override
  public String getName(){
    return "";
  }

  @Override
  public void init(PsiElement element){
    myFile = (XmlFile) element.getContainingFile();

    if (element instanceof XmlTag) {
      myTag = (XmlTag)element;
    } else {
      final XmlDocument document = myFile.getDocument();

      if (document != null) {
        myTag = document.getRootTag();
      }
    }

    if (myTag != null) {
      myTargetNamespace = myTag.getAttributeValue("targetNamespace");
    }

    final THashSet<PsiFile> dependenciesSet = new THashSet<PsiFile>();
    final Set<PsiFile> redefineProcessingSet = myRedefinedDescriptorsInProcessing.get();
    if (redefineProcessingSet != null) {
      dependenciesSet.addAll(redefineProcessingSet);
    }
    collectDependencies(myTag, myFile, dependenciesSet);
    dependencies = ArrayUtil.toObjectArray(dependenciesSet);
  }

  @Override
  public Object[] getDependences() {
    if (dependencies == null) dependencies = myFile == null ? ArrayUtil.EMPTY_OBJECT_ARRAY : new Object[] {myFile}; // init was not called
    return dependencies;
  }
  static {
    STD_TYPES.add("string");
    STD_TYPES.add("normalizedString");
    STD_TYPES.add("token");
    STD_TYPES.add("byte");
    STD_TYPES.add("unsignedByte");
    STD_TYPES.add("base64Binary");
    STD_TYPES.add("hexBinary");
    STD_TYPES.add("integer");
    STD_TYPES.add("positiveInteger");
    STD_TYPES.add("negativeInteger");
    STD_TYPES.add("nonNegativeInteger");
    STD_TYPES.add("nonPositiveInteger");
    STD_TYPES.add("int");
    STD_TYPES.add("unsignedInt");
    STD_TYPES.add("long");
    STD_TYPES.add("unsignedLong");
    STD_TYPES.add("short");
    STD_TYPES.add("unsignedShort");
    STD_TYPES.add("decimal");
    STD_TYPES.add("float");
    STD_TYPES.add("double");
    STD_TYPES.add("boolean");
    STD_TYPES.add("time");
    STD_TYPES.add("dateTime");
    STD_TYPES.add("duration");
    STD_TYPES.add("date");
    STD_TYPES.add("gMonth");
    STD_TYPES.add("gYear");
    STD_TYPES.add("gYearMonth");
    STD_TYPES.add("gDay");
    STD_TYPES.add("gMonthDay");
    STD_TYPES.add("Name");
    STD_TYPES.add("QName");
    STD_TYPES.add("NCName");
    STD_TYPES.add("anyURI");
    STD_TYPES.add("language");
    STD_TYPES.add("ID");
    STD_TYPES.add("IDREF");
    STD_TYPES.add("IDREFS");
    STD_TYPES.add("ENTITY");
    STD_TYPES.add("ENTITIES");
    STD_TYPES.add("NOTATION");
    STD_TYPES.add("NMTOKEN");
    STD_TYPES.add("NMTOKENS");
    STD_TYPES.add("anySimpleType");

    UNDECLARED_STD_TYPES.add("anySimpleType");
  }

  @Override
  public void validate(@NotNull XmlDocument context, @NotNull Validator.ValidationHost host) {
    ExternalDocumentValidator.doValidation(context,host);
  }

  public XmlTag getTag() {
    return myTag;
  }

  public boolean hasSubstitutions() {
    initSubstitutes();
    return mySubstitutions != null && mySubstitutions.size() > 0;
  }

  public boolean isValid() {
    return myFile != null && getDeclaration().isValid();
  }

  static class QNameKey extends Pair<String, String>{
     QNameKey(String name, String namespace) {
      super(name, namespace);
    }
  }
}
