/*
 * 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.psi.ElementManipulators;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.meta.PsiWritableMetaData;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.xml.*;
import com.intellij.xml.util.XmlEnumeratedValueReference;
import com.intellij.xml.util.XmlUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

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

/**
 * @author Mike
 */
public class XmlElementDescriptorImpl extends XsdEnumerationDescriptor<XmlTag>
  implements XmlElementDescriptor, PsiWritableMetaData, Validator<XmlTag>,
                                                 XmlElementDescriptorAwareAboutChildren {
  protected XmlTag myDescriptorTag;
  protected volatile XmlNSDescriptor NSDescriptor;
  private volatile @Nullable Validator<XmlTag> myValidator;

  @NonNls
  public static final String QUALIFIED_ATTR_VALUE = "qualified";
  @NonNls
  public static final String NONQUALIFIED_ATTR_VALUE = "unqualified";
  @NonNls
  private static final String ELEMENT_FORM_DEFAULT = "elementFormDefault";

  public XmlElementDescriptorImpl(@Nullable XmlTag descriptorTag) {
    myDescriptorTag = descriptorTag;
  }

  public XmlElementDescriptorImpl() {}

  @Override
  public XmlTag getDeclaration(){
    return myDescriptorTag;
  }

  @Override
  public String getName(PsiElement context){
    String value = myDescriptorTag.getAttributeValue("name");

    if(context instanceof XmlElement){
      final String namespace = getNamespaceByContext(context);
      final XmlTag tag = PsiTreeUtil.getParentOfType(context, XmlTag.class, false);

      if(tag != null){
        final String namespacePrefix = tag.getPrefixByNamespace(namespace);

        if (namespacePrefix != null && namespacePrefix.length() > 0) {
          final XmlTag rootTag = ((XmlFile)myDescriptorTag.getContainingFile()).getRootTag();
          String elementFormDefault;

          if (rootTag != null && 
              ( NONQUALIFIED_ATTR_VALUE.equals(elementFormDefault = rootTag.getAttributeValue(ELEMENT_FORM_DEFAULT)) || elementFormDefault == null /*unqualified is default*/) &&
              tag.getNamespaceByPrefix("").isEmpty()
            && myDescriptorTag.getParentTag() != rootTag
             ) {
            value = XmlUtil.findLocalNameByQualifiedName(value);
          } else {
            value = namespacePrefix + ":" + XmlUtil.findLocalNameByQualifiedName(value);
          }
        }
      }
    }
    return value;
  }

  /** getter for _local_ name */
  @Override
  public String getName() {
    return XmlUtil.findLocalNameByQualifiedName(getName(null));
  }

  public String getNamespaceByContext(PsiElement context){
    //while(context != null){
    //  if(context instanceof XmlTag){
    //    final XmlTag contextTag = ((XmlTag)context);
    //    final XmlNSDescriptorImpl schemaDescriptor = XmlUtil.findXmlNSDescriptorByType(contextTag);
    //    if (schemaDescriptor != null) {
    //      return schemaDescriptor.getDefaultNamespace();
    //    }
    //  }
    //  context = context.getContext();
    //}
    return getNamespace();
  }

  public String getNamespace(){
    String name = getName();
    if (name == null) return XmlUtil.EMPTY_URI;
    final XmlNSDescriptorImpl xmlNSDescriptor = (XmlNSDescriptorImpl)getNSDescriptor();
    if (xmlNSDescriptor == null || myDescriptorTag == null) return XmlUtil.EMPTY_URI;
    final String namespacePrefix = XmlUtil.findPrefixByQualifiedName(name);
    return namespacePrefix.isEmpty() ?
           xmlNSDescriptor.getDefaultNamespace() :
           myDescriptorTag.getNamespaceByPrefix(namespacePrefix);
  }

  @Override
  public void init(PsiElement element){
    if (myDescriptorTag!=element && myDescriptorTag!=null) {
      NSDescriptor = null;
    }
    myDescriptorTag = (XmlTag) element;
  }

  @Override
  public Object[] getDependences(){
    return new Object[]{myDescriptorTag};
  }

  private XmlNSDescriptor getNSDescriptor(XmlElement context) {
    XmlNSDescriptor nsDescriptor = getNSDescriptor();
    if (context instanceof XmlTag && nsDescriptor instanceof XmlNSDescriptorImpl) {
      final String defaultNamespace = ((XmlNSDescriptorImpl)nsDescriptor).getDefaultNamespace();
      if (XmlUtil.XML_SCHEMA_URI.equals(defaultNamespace)) return nsDescriptor; // do not check for overriden for efficiency

      final XmlTag tag = (XmlTag)context;
      final String tagNs = tag.getNamespace();
      if (tagNs.equals(defaultNamespace)) {
        XmlNSDescriptor previousDescriptor = nsDescriptor;
        nsDescriptor = tag.getNSDescriptor(tagNs, true);
        if (nsDescriptor == null) nsDescriptor = previousDescriptor;
      }
    }
    
    return nsDescriptor;
  }

  @Override
  public XmlNSDescriptor getNSDescriptor() {
    XmlNSDescriptor nsDescriptor = NSDescriptor;
    if (nsDescriptor == null || !NSDescriptor.getDeclaration().isValid()) {
      final XmlFile file = XmlUtil.getContainingFile(getDeclaration());
      if(file == null) return null;
      final XmlDocument document = file.getDocument();
      if(document == null) return null;
      NSDescriptor = nsDescriptor = (XmlNSDescriptor)document.getMetaData();
    }

    return nsDescriptor;
  }

  @Override
  public XmlElementsGroup getTopGroup() {
    TypeDescriptor type = getType();
    return type instanceof ComplexTypeDescriptor ? ((ComplexTypeDescriptor)type).getTopGroup() : null;
  }

  @Nullable
  public TypeDescriptor getType() {
    return getType(null);
  }

  @Nullable
  public TypeDescriptor getType(XmlElement context) {
    final XmlNSDescriptor nsDescriptor = getNSDescriptor(context);
    if (!(nsDescriptor instanceof XmlNSTypeDescriptorProvider)) return null;

    TypeDescriptor type = ((XmlNSTypeDescriptorProvider) nsDescriptor).getTypeDescriptor(myDescriptorTag);
    if (type == null) {
      String substAttr = myDescriptorTag.getAttributeValue("substitutionGroup");
      if (substAttr != null) {
        final String namespacePrefix = XmlUtil.findPrefixByQualifiedName(substAttr);
        final String namespace = namespacePrefix.isEmpty() ?
                                 ((XmlNSDescriptorImpl)getNSDescriptor()).getDefaultNamespace() :
                                 myDescriptorTag.getNamespaceByPrefix(namespacePrefix);
        final String local = XmlUtil.findLocalNameByQualifiedName(substAttr);
        final XmlElementDescriptorImpl originalElement = (XmlElementDescriptorImpl)((XmlNSDescriptorImpl)getNSDescriptor()).getElementDescriptor(local, namespace);
        if (originalElement != null) {
          type = originalElement.getType(context);
        }
      }
    }
    return type;
  }

  @Override
  public XmlElementDescriptor[] getElementsDescriptors(XmlTag context) {
    if (context != null) {
      final XmlElementDescriptor parentDescriptorByType = XmlUtil.findXmlDescriptorByType(context);
      if (parentDescriptorByType != null && !parentDescriptorByType.equals(this)) {
        return parentDescriptorByType.getElementsDescriptors(context);
      }
    }

    XmlElementDescriptor[] elementsDescriptors = getElementsDescriptorsImpl(context);

    final TypeDescriptor type = getType(context);

    if (type instanceof ComplexTypeDescriptor) {
      final ComplexTypeDescriptor descriptor = (ComplexTypeDescriptor)type;
      String contextNs;
      PsiFile containingFile = context != null ? context.getContainingFile():null;

      if (context != null && !containingFile.isPhysical()) {
        containingFile = containingFile.getOriginalFile();
        //context = context.getParentTag();
      }

      if (context != null &&
          ( descriptor.canContainTag(context.getLocalName(), contextNs = context.getNamespace(), context ) &&
            (!contextNs.equals(getNamespace()) || descriptor.hasAnyInContentModel())
          ) ) {
        final XmlNSDescriptor nsDescriptor = getNSDescriptor();

        if (nsDescriptor != null) {
          elementsDescriptors = ArrayUtil.mergeArrays(
            elementsDescriptors,
            nsDescriptor.getRootElementsDescriptors(((XmlFile)containingFile).getDocument())
          );
        }
      }
    }

    return elementsDescriptors;
  }

  private XmlElementDescriptor[] getElementsDescriptorsImpl(XmlElement context) {
    TypeDescriptor type = getType(context);

    if (type instanceof ComplexTypeDescriptor) {
      ComplexTypeDescriptor typeDescriptor = (ComplexTypeDescriptor)type;

      XmlElementDescriptor[] elements = typeDescriptor.getElements(context);
      if (context instanceof XmlTag && elements.length > 0) {
        String[] namespaces = ((XmlTag)context).knownNamespaces();
        if (namespaces.length > 1) {
          List<XmlElementDescriptor> result = new ArrayList<XmlElementDescriptor>(Arrays.asList(elements));
          for (String namespace : namespaces) {
            if (namespace.equals(typeDescriptor.getNsDescriptor().getDefaultNamespace())) {
              continue;
            }
            XmlNSDescriptor descriptor = ((XmlTag)context).getNSDescriptor(namespace, false);
            if (descriptor instanceof XmlNSDescriptorImpl && ((XmlNSDescriptorImpl)descriptor).hasSubstitutions()) {
              for (XmlElementDescriptor element : elements) {
                String name = XmlUtil.getLocalName(element.getName(context)).toString();
                String s = ((XmlNSDescriptorImpl)element.getNSDescriptor()).getDefaultNamespace();
                XmlElementDescriptor[] substitutes = ((XmlNSDescriptorImpl)descriptor).getSubstitutes(name, s);
                result.addAll(Arrays.asList(substitutes));
              }
            }
          }
          return result.toArray(new XmlElementDescriptor[result.size()]);
        }
      }
      return elements;
    }

    return EMPTY_ARRAY;
  }

  @Override
  public XmlAttributeDescriptor[] getAttributesDescriptors(final XmlTag context) {

    TypeDescriptor type = getType(context);

    if (type instanceof ComplexTypeDescriptor) {
      ComplexTypeDescriptor typeDescriptor = (ComplexTypeDescriptor)type;
      XmlAttributeDescriptor[] attributeDescriptors = typeDescriptor.getAttributes(context);

      if (context != null) {
        final String contextNs = context.getNamespace();

        boolean seenXmlNs = false;
        for(String ns:context.knownNamespaces()) {
          if (!contextNs.equals(ns) && ns.length() > 0) {
            seenXmlNs |= XmlUtil.XML_NAMESPACE_URI.equals(ns);
            attributeDescriptors = updateAttributeDescriptorsFromAny(context, typeDescriptor, attributeDescriptors, ns);
          }
        }

        if (!seenXmlNs) {
          attributeDescriptors = updateAttributeDescriptorsFromAny(context, typeDescriptor, attributeDescriptors, XmlUtil.XML_NAMESPACE_URI);
        }
      }
      return attributeDescriptors;
    }

    return XmlAttributeDescriptor.EMPTY;
  }

  /** <xsd:anyAttribute> directive processed here */
  private static XmlAttributeDescriptor[] updateAttributeDescriptorsFromAny(final XmlTag context,
                                                                            final ComplexTypeDescriptor typeDescriptor,
                                                                            XmlAttributeDescriptor[] attributeDescriptors,
                                                                            final String ns) {
    if (typeDescriptor.canContainAttribute(ns, null) != ComplexTypeDescriptor.CanContainAttributeType.CanNotContain) {
      // anyAttribute found
      final XmlNSDescriptor descriptor = context.getNSDescriptor(ns, true);

      if (descriptor instanceof XmlNSDescriptorImpl) {
        XmlAttributeDescriptor[] rootDescriptors = ((XmlNSDescriptorImpl)descriptor).getRootAttributeDescriptors(context);
        attributeDescriptors = ArrayUtil.mergeArrays(attributeDescriptors, rootDescriptors);
      }
    }
    return attributeDescriptors;
  }

  @Override
  public XmlAttributeDescriptor getAttributeDescriptor(String attributeName, final XmlTag context){
    return getAttributeDescriptorImpl(attributeName,context);
  }

  @Nullable
  private XmlAttributeDescriptor getAttributeDescriptorImpl(final String attributeName, XmlTag context) {
    final String localName = XmlUtil.findLocalNameByQualifiedName(attributeName);
    final String namespacePrefix = XmlUtil.findPrefixByQualifiedName(attributeName);
    final XmlNSDescriptorImpl xmlNSDescriptor = (XmlNSDescriptorImpl)getNSDescriptor();
    final String namespace = namespacePrefix.isEmpty() ?
                             ((xmlNSDescriptor != null)?xmlNSDescriptor.getDefaultNamespace():"") :
                             context.getNamespaceByPrefix(namespacePrefix);

    XmlAttributeDescriptor attribute = getAttribute(localName, namespace, context, attributeName);
    
    if (attribute instanceof AnyXmlAttributeDescriptor) {
      final ComplexTypeDescriptor.CanContainAttributeType containAttributeType =
        ((AnyXmlAttributeDescriptor)attribute).getCanContainAttributeType();
      if (containAttributeType != ComplexTypeDescriptor.CanContainAttributeType.CanContainAny && !namespace.isEmpty()) {
        final XmlNSDescriptor candidateNSDescriptor = context.getNSDescriptor(namespace, true);

        if (candidateNSDescriptor instanceof XmlNSDescriptorImpl) {
          final XmlNSDescriptorImpl nsDescriptor = (XmlNSDescriptorImpl)candidateNSDescriptor;

          final XmlAttributeDescriptor xmlAttributeDescriptor = nsDescriptor.getAttribute(localName, namespace, context);
          if (xmlAttributeDescriptor != null) return xmlAttributeDescriptor;
          else {
            if (containAttributeType == ComplexTypeDescriptor.CanContainAttributeType.CanContainButDoNotSkip) {
              attribute = null;
            }
          }
        }
      }
    }
    return attribute;
  }

  @Override
  public XmlAttributeDescriptor getAttributeDescriptor(XmlAttribute attribute){
    return getAttributeDescriptorImpl(attribute.getName(),attribute.getParent());
  }

  @Nullable
  private XmlAttributeDescriptor getAttribute(String attributeName, String namespace, XmlTag context, String qName) {
    XmlAttributeDescriptor[] descriptors = getAttributesDescriptors(context);

    for (XmlAttributeDescriptor descriptor : descriptors) {
      if (descriptor.getName().equals(attributeName) &&
          descriptor.getName(context).equals(qName)
         ) {
        return descriptor;
      }
    }

    TypeDescriptor type = getType(context);
    if (type instanceof ComplexTypeDescriptor) {
      ComplexTypeDescriptor descriptor = (ComplexTypeDescriptor)type;
      final ComplexTypeDescriptor.CanContainAttributeType containAttributeType = descriptor.canContainAttribute(namespace, qName);

      if (containAttributeType != ComplexTypeDescriptor.CanContainAttributeType.CanNotContain) {
        return new AnyXmlAttributeDescriptor(attributeName, containAttributeType);
      }
    }

    return null;
  }

  @Override
  public int getContentType() {
    TypeDescriptor type = getType();

    if (type instanceof ComplexTypeDescriptor) {
      return ((ComplexTypeDescriptor)type).getContentType();
    }

    return CONTENT_TYPE_MIXED;
  }

  @Nullable
  public XmlElementDescriptor getElementDescriptor(final String name) {
      final String localName = XmlUtil.findLocalNameByQualifiedName(name);
      final String namespacePrefix = XmlUtil.findPrefixByQualifiedName(name);
      final String namespace = namespacePrefix.isEmpty() ?
                               ((XmlNSDescriptorImpl)getNSDescriptor()).getDefaultNamespace() :
                               myDescriptorTag.getNamespaceByPrefix(namespacePrefix);
    return getElementDescriptor(localName, namespace, null, name);
  }

  @Nullable
  protected XmlElementDescriptor getElementDescriptor(final String localName, final String namespace, XmlElement context, String fullName) {
    XmlElementDescriptor[] elements = getElementsDescriptorsImpl(context);

    for (XmlElementDescriptor element1 : elements) {
      final XmlElementDescriptorImpl element = (XmlElementDescriptorImpl)element1;
      final String namespaceByContext = element.getNamespaceByContext(context);

      if (element.getName().equals(localName)) {
        if (namespace == null ||
            namespace.equals(namespaceByContext) ||
            namespaceByContext.equals(XmlUtil.EMPTY_URI) ||
            element.getName(context).equals(fullName) || (namespace.length() == 0) &&
                                                         element.getDefaultName().equals(fullName)
           ) {
          return element;
        }
        else {
          final XmlNSDescriptor descriptor = context instanceof XmlTag? ((XmlTag)context).getNSDescriptor(namespace, true) : null;

          // schema's targetNamespace could be different from file systemId used as NS
          if (descriptor instanceof XmlNSDescriptorImpl) {
            if (((XmlNSDescriptorImpl)descriptor).getDefaultNamespace().equals(namespaceByContext)) {
              return element;
            }
            else {
              ((XmlNSDescriptorImpl)descriptor).getSubstitutes(localName, namespace);
            }
          }
        }
      }
    }

    TypeDescriptor type = getType(context);
    if (type instanceof ComplexTypeDescriptor) {
      ComplexTypeDescriptor descriptor = (ComplexTypeDescriptor)type;
      if (descriptor.canContainTag(localName, namespace, context)) {
        return new AnyXmlElementDescriptor(this, getNSDescriptor());
      }
    }

    return null;
  }

  @Override
  public XmlElementDescriptor getElementDescriptor(XmlTag element, XmlTag contextTag){
    final XmlElement context = (XmlElement)element.getParent();

    XmlElementDescriptor elementDescriptor = getElementDescriptor(
      element.getLocalName(),
      element.getNamespace(), context,
      element.getName()
    );

    if(elementDescriptor == null || element.getAttributeValue("xsi:type") != null){
      final XmlElementDescriptor xmlDescriptorByType = XmlUtil.findXmlDescriptorByType(element);

      if (xmlDescriptorByType != null) elementDescriptor = xmlDescriptorByType;
      else if (context instanceof XmlTag && ((XmlTag)context).getAttributeValue("xsi:type") != null && askParentDescriptorViaXsi()) {
        final XmlElementDescriptor parentXmlDescriptorByType = XmlUtil.findXmlDescriptorByType(((XmlTag)context));
        if (parentXmlDescriptorByType != null) {
          elementDescriptor = parentXmlDescriptorByType.getElementDescriptor(element, contextTag);
        }
      }
    }
    return elementDescriptor;
  }

  protected boolean askParentDescriptorViaXsi() {
    return true;
  }

  @Override
  public String getQualifiedName() {
    String ns = getNS();
    if (ns != null && !ns.isEmpty()) {
      return ns + ":" + getName();
    }

    return getName();
  }

  @Nullable
  private String getNS(){
    return XmlUtil.findNamespacePrefixByURI((XmlFile) myDescriptorTag.getContainingFile(), getNamespace());
  }

  @Override
  public String getDefaultName() {
    final PsiFile psiFile = myDescriptorTag.getContainingFile();
    XmlTag rootTag = psiFile instanceof XmlFile ?((XmlFile)psiFile).getRootTag():null;

    if (rootTag != null && QUALIFIED_ATTR_VALUE.equals(rootTag.getAttributeValue(ELEMENT_FORM_DEFAULT))) {
      return getQualifiedName();
    }

    return getName();
  }

  public boolean isAbstract() {
    return isAbstractDeclaration(myDescriptorTag);
  }

  public static Boolean isAbstractDeclaration(final XmlTag descriptorTag) {
    return Boolean.valueOf(descriptorTag.getAttributeValue("abstract"));
  }

  @Override
  public void setName(String name) throws IncorrectOperationException {
    NamedObjectDescriptor.setName(myDescriptorTag, name);
  }

  public void setValidator(final Validator<XmlTag> validator) {
    myValidator = validator;
  }

  @Override
  public void validate(@NotNull XmlTag context, @NotNull ValidationHost host) {
    Validator<XmlTag> validator = myValidator;
    if (validator != null) {
      validator.validate(context, host);
    }
  }

  @Override
  public PsiReference[] getValueReferences(XmlTag xmlTag, @NotNull String text) {
    XmlTagValue value = xmlTag.getValue();
    XmlText[] elements = value.getTextElements();
    if (elements.length == 0 || xmlTag.getSubTags().length > 0) return PsiReference.EMPTY_ARRAY;
    return new PsiReference[] {
      new XmlEnumeratedValueReference(xmlTag, this, ElementManipulators.getValueTextRange(xmlTag))
    };
  }

  @Override
  public boolean allowElementsFromNamespace(final String namespace, final XmlTag context) {
    final TypeDescriptor type = getType(context);
    
    if (type instanceof ComplexTypeDescriptor) {
      final ComplexTypeDescriptor typeDescriptor = (ComplexTypeDescriptor)type;
      return typeDescriptor.canContainTag("a", namespace, context) ||
             typeDescriptor.getNsDescriptor().hasSubstitutions() ||
             XmlUtil.nsFromTemplateFramework(namespace)
        ;
    }
    return false;
  }

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

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    XmlElementDescriptorImpl that = (XmlElementDescriptorImpl)o;

    if (myDescriptorTag != null ? !myDescriptorTag.equals(that.myDescriptorTag) : that.myDescriptorTag != null) return false;

    return true;
  }

  @Override
  public int hashCode() {
    return myDescriptorTag != null ? myDescriptorTag.hashCode() : 0;
  }
}
