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

import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.psi.PsiElement;
import com.intellij.psi.xml.XmlTag;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;

/**
 * If converter extends this class, the corresponding XML {@link com.intellij.psi.PsiReference}
 * will take completion variants from {@link #getVariants(ConvertContext)} method.
 *
 * @author peter
 */
public abstract class ResolvingConverter<T> extends Converter<T> {
  @Deprecated
  public static final ResolvingConverter EMPTY_CONVERTER = new ResolvingConverter() {
    @Override
    @NotNull
    public Collection getVariants(final ConvertContext context) {
      return Collections.emptyList();
    }

    @Override
    public Object fromString(final String s, final ConvertContext context) {
      return s;
    }

    @Override
    public String toString(final Object t, final ConvertContext context) {
      return String.valueOf(t);
    }
  };

  /** @see com.intellij.util.xml.converters.values.BooleanValueConverter */
  @Deprecated
  public static final Converter<Boolean> BOOLEAN_CONVERTER = new ResolvingConverter<Boolean>() {
    @Override
    public Boolean fromString(final String s, final ConvertContext context) {
      if ("true".equalsIgnoreCase(s)) {
        return Boolean.TRUE;
      }
      if ("false".equalsIgnoreCase(s)) {
        return Boolean.FALSE;
      }
      return null;
    }

    @Override
    public String toString(final Boolean t, final ConvertContext context) {
      return t == null? null:t.toString();
    }

    @Override
    @NotNull
    public Collection<? extends Boolean> getVariants(final ConvertContext context) {
      final DomElement element = context.getInvocationElement();
      if (element instanceof GenericDomValue) {
        final SubTag annotation = element.getAnnotation(SubTag.class);
        if (annotation != null && annotation.indicator()) return Collections.emptyList();
      }

      return Arrays.asList(Boolean.FALSE, Boolean.TRUE);
    }
  };

  @Override
  public String getErrorMessage(@Nullable String s, final ConvertContext context) {
    return CodeInsightBundle.message("error.cannot.resolve.default.message", s);
  }

  /**
   * @param context context
   * @return reference completion variants
   */
  @NotNull
  public abstract Collection<? extends T> getVariants(final ConvertContext context);

  /**
   * @return additional reference variants. They won't resolve to anywhere, but won't be highlighted as errors.
   * They will also appear in the completion dropdown.
   */
  @Deprecated
  @NotNull
  public Set<String> getAdditionalVariants() {
    return Collections.emptySet();
  }
  /**
   * @return additional reference variants. They won't resolve to anywhere, but won't be highlighted as errors.
   * They will also appear in the completion dropdown.
   */
  @NotNull
  public Set<String> getAdditionalVariants(@NotNull final ConvertContext context) {
    return getAdditionalVariants();
  }

  /**
   * Delegate from {@link com.intellij.psi.PsiReference#handleElementRename(String)}
   * @param genericValue generic value
   * @param context context
   * @param newElementName new element name
   */
  public void handleElementRename(final GenericDomValue<T> genericValue, final ConvertContext context,
                                  final String newElementName) {
    genericValue.setStringValue(newElementName);
  }

  /**
   * Delegate from {@link com.intellij.psi.PsiReference#bindToElement(com.intellij.psi.PsiElement)}
   * @param genericValue generic value
   * @param context context
   * @param newTarget new target
   */
  public void bindReference(final GenericDomValue<T> genericValue, final ConvertContext context, final PsiElement newTarget) {
    if (newTarget instanceof XmlTag) {
      DomElement domElement = genericValue.getManager().getDomElement((XmlTag) newTarget);
      if (domElement != null) {
        genericValue.setStringValue(ElementPresentationManager.getElementName(domElement));
      }
    }
  }

  /**
   * @param resolvedValue {@link #fromString(String, ConvertContext)} result
   * @return the PSI element to which the {@link com.intellij.psi.PsiReference} will resolve
   */
  @Nullable
  public PsiElement getPsiElement(@Nullable T resolvedValue) {
    if (resolvedValue instanceof PsiElement) {
      return (PsiElement)resolvedValue;
    }
    if (resolvedValue instanceof DomElement) {
      return ((DomElement)resolvedValue).getXmlElement();
    }
    return null;
  }

  /**
   * Delegate from {@link com.intellij.psi.PsiReference#isReferenceTo(com.intellij.psi.PsiElement)}
   * @param element element
   * @param stringValue string value
   * @param resolveResult resolve result
   * @param context context
   * @return is reference to?
   */
  public boolean isReferenceTo(@NotNull PsiElement element, final String stringValue, @Nullable T resolveResult,
                               final ConvertContext context) {
    return resolveResult != null && element.getManager().areElementsEquivalent(element, getPsiElement(resolveResult));
  }

  /**
   * Delegate from {@link com.intellij.psi.PsiReference#resolve()}
   * @param o {@link #fromString(String, ConvertContext)} result
   * @param context context
   * @return PSI element to resolve to. By default calls {@link #getPsiElement(Object)} method
   */
  @Nullable
  public PsiElement resolve(final T o, final ConvertContext context) {
    final PsiElement psiElement = getPsiElement(o);
    return psiElement == null && o != null ? DomUtil.getValueElement((GenericDomValue)context.getInvocationElement()) : psiElement;
  }

  /**
   * @param context context
   * @return LocalQuickFix'es to correct non-resolved value (e.g. 'create from usage')
   */
  public LocalQuickFix[] getQuickFixes(final ConvertContext context) {
    return LocalQuickFix.EMPTY_ARRAY;
  }

  /**
   * Override to provide custom lookup elements in completion.
   * <p/>
   * Default is {@code null} which will create lookup via
   * {@link ElementPresentationManager#createVariant(java.lang.Object, java.lang.String, com.intellij.psi.PsiElement)}.
   *
   * @param t DOM to create lookup element for.
   * @return Lookup element.
   */
  @Nullable
  public LookupElement createLookupElement(T t) {
    return null;
  }

  /**
   * Adds {@link #getVariants(ConvertContext)} functionality to a simple String value.
   */
  public static abstract class StringConverter extends ResolvingConverter<String> {

    @Override
    public String fromString(final String s, final ConvertContext context) {
      return s;
    }

    @Override
    public String toString(final String s, final ConvertContext context) {
      return s;
    }
  }

  /**
   * Adds {@link #getVariants(ConvertContext)} functionality to an existing converter. 
   */
  public static abstract class WrappedResolvingConverter<T> extends ResolvingConverter<T> {

    private final Converter<T> myWrappedConverter;

    public WrappedResolvingConverter(Converter<T> converter) {

      myWrappedConverter = converter;
    }

    @Override
    public T fromString(final String s, final ConvertContext context) {
      return myWrappedConverter.fromString(s, context);
    }

    @Override
    public String toString(final T t, final ConvertContext context) {
      return myWrappedConverter.toString(t, context);
    }
  }
}
