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

import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.ide.DataManager;
import com.intellij.ide.TypePresentationService;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.editor.Editor;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.xml.*;
import com.intellij.util.xml.reflect.DomCollectionChildDescription;
import com.intellij.util.xml.reflect.DomGenericInfo;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.lang.reflect.Type;
import java.util.List;

/**
 * @author Dmitry Avdeev
*/
public class ResolvingElementQuickFix implements LocalQuickFix, IntentionAction {

  private final Class<? extends DomElement> myClazz;
  private final String myNewName;
  private final List<DomElement> myParents;
  private final DomCollectionChildDescription myChildDescription;
  private String myTypeName;

  public ResolvingElementQuickFix(final Class<? extends DomElement> clazz, final String newName, final List<DomElement> parents,
                                  final DomCollectionChildDescription childDescription) {
    myClazz = clazz;
    myNewName = newName;
    myParents = parents;
    myChildDescription = childDescription;

    myTypeName = TypePresentationService.getService().getTypePresentableName(myClazz);
  }

  public void setTypeName(final String typeName) {
    myTypeName = typeName;
  }

  @Override
  @NotNull
  public String getName() {
    return DomBundle.message("create.new.element", myTypeName, myNewName);
  }

  @Override
  @NotNull
  public String getText() {
    return getName();
  }

  @Override
  @NotNull
  public String getFamilyName() {
    return DomBundle.message("quick.fixes.family");
  }

  @Override
  public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
    return true;
  }

  @Override
  public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
    applyFix();
  }

  @Override
  public boolean startInWriteAction() {
    return false;
  }

  @Override
  public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
    applyFix();
  }

  private void applyFix() {
    chooseParent(myParents, new Consumer<DomElement>() {
      @Override
      public void consume(final DomElement parent) {
        new WriteCommandAction.Simple(parent.getManager().getProject(), DomUtil.getFile(parent)) {
          @Override
          protected void run() throws Throwable {
            doFix(parent, myChildDescription, myNewName);
          }
        }.execute();
      }
    });
  }

  protected DomElement doFix(DomElement parent, final DomCollectionChildDescription childDescription, String newName) {
    final DomElement domElement = childDescription.addValue(parent);
    final GenericDomValue nameDomElement = domElement.getGenericInfo().getNameDomElement(domElement);
    assert nameDomElement != null;
    nameDomElement.setStringValue(newName);
    return domElement;
  }

  protected static void chooseParent(final List<DomElement> files, final Consumer<DomElement> onChoose) {
    switch (files.size()) {
      case 0:
        return;
      case 1:
        onChoose.consume(files.iterator().next());
        return;
      default:
        JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<DomElement>(DomBundle.message("choose.file"), files) {
          @Override
          public PopupStep onChosen(final DomElement selectedValue, final boolean finalChoice) {
            onChoose.consume(selectedValue);
            return super.onChosen(selectedValue, finalChoice);
          }

          @Override
          public Icon getIconFor(final DomElement aValue) {
            return DomUtil.getFile(aValue).getIcon(0);
          }

          @Override
          @NotNull
          public String getTextFor(final DomElement value) {
            final String name = DomUtil.getFile(value).getName();
            assert name != null;
            return name;
          }
        }).showInBestPositionFor(DataManager.getInstance().getDataContext());
    }
  }

  @Nullable
  public static <T extends DomElement> DomCollectionChildDescription getChildDescription(final List<DomElement> contexts, Class<T> clazz) {

    if (contexts.size() == 0) {
        return null;
    }
    final DomElement context = contexts.get(0);
    final DomGenericInfo genericInfo = context.getGenericInfo();
    final List<? extends DomCollectionChildDescription> descriptions = genericInfo.getCollectionChildrenDescriptions();
    for (DomCollectionChildDescription description : descriptions) {
      final Type type = description.getType();
      if (type.equals(clazz)) {
        return description;
      }
    }
    return null;
  }

  @Nullable
  public static ResolvingElementQuickFix createFix(final String newName, final Class<? extends DomElement> clazz, final DomElement scope) {
    final List<DomElement> parents = ModelMergerUtil.getImplementations(scope);
    return createFix(newName, clazz, parents);
  }

  @Nullable
  public static ResolvingElementQuickFix createFix(final String newName, final Class<? extends DomElement> clazz, final List<DomElement> parents) {
    final DomCollectionChildDescription childDescription = getChildDescription(parents, clazz);
    if (newName.length() > 0 && childDescription != null) {
      return new ResolvingElementQuickFix(clazz, newName, parents, childDescription);
    }
    return null;
  }

  public static LocalQuickFix[] createFixes(final String newName, Class<? extends DomElement> clazz, final DomElement scope) {
    final LocalQuickFix fix = createFix(newName, clazz, scope);
    return fix != null ? new LocalQuickFix[] { fix } : LocalQuickFix.EMPTY_ARRAY;
  }
}
