/*
 * Copyright 2000-2013 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.codeInspection.javaDoc;

import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.quickfix.ImportClassFix;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemDescriptorBase;
import com.intellij.ide.DataManager;
import com.intellij.ide.util.FQNameCellRenderer;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.proximity.PsiProximityComparator;
import com.intellij.ui.components.JBList;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

public class JavaDocReferenceInspection extends JavaDocReferenceInspectionBase {
  @Override
  protected LocalQuickFix createAddQualifierFix(PsiJavaCodeReferenceElement reference) {
    List<PsiClass> classesToImport = new ImportClassFix(reference).getClassesToImport();
    return classesToImport.isEmpty() ? null : new JavaDocReferenceInspection.AddQualifierFix(classesToImport);
  }
  @Override
  protected RenameReferenceQuickFix createRenameReferenceQuickFix(Set<String> unboundParams) {
    return new RenameReferenceQuickFix(unboundParams);
  }

  private static class RenameReferenceQuickFix implements LocalQuickFix {
    private final Set<String> myUnboundParams;

    public RenameReferenceQuickFix(Set<String> unboundParams) {
      myUnboundParams = unboundParams;
    }

    @Override
    @NotNull
    public String getName() {
      return "Change to ...";
    }

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

    @Override
    public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
      final AsyncResult<DataContext> asyncResult = DataManager.getInstance().getDataContextFromFocus();
      asyncResult.doWhenDone(new Consumer<DataContext>() {
        @Override
        public void consume(DataContext dataContext) {
          final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
          assert editor != null;
          final TextRange textRange = ((ProblemDescriptorBase)descriptor).getTextRange();
          editor.getSelectionModel().setSelection(textRange.getStartOffset(), textRange.getEndOffset());

          final String word = editor.getSelectionModel().getSelectedText();

          if (word == null || StringUtil.isEmptyOrSpaces(word)) {
            return;
          }
          final List<LookupElement> items = new ArrayList<LookupElement>();
          for (String variant : myUnboundParams) {
            items.add(LookupElementBuilder.create(variant));
          }
          LookupManager.getInstance(project).showLookup(editor, items.toArray(new LookupElement[items.size()]));
        }
      });
    }
  }

  private class AddQualifierFix implements LocalQuickFix{
    private final List<PsiClass> originalClasses;

    public AddQualifierFix(final List<PsiClass> originalClasses) {
      this.originalClasses = originalClasses;
    }

    @Override
    @NotNull
    public String getName() {
      return QuickFixBundle.message("add.qualifier");
    }

    @Override
    @NotNull
    public String getFamilyName() {
      return QuickFixBundle.message("add.qualifier");
    }

    @Override
    public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
      final PsiElement element = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiJavaCodeReferenceElement.class);
      if (element instanceof PsiJavaCodeReferenceElement) {
        final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement)element;
        Collections.sort(originalClasses, new PsiProximityComparator(referenceElement.getElement()));
        final JList list = new JBList(originalClasses.toArray(new PsiClass[originalClasses.size()]));
        list.setCellRenderer(new FQNameCellRenderer());
        final Runnable runnable = new Runnable() {
          @Override
          public void run() {
            if (!element.isValid()) return;
            final int index = list.getSelectedIndex();
            if (index < 0) return;
            new WriteCommandAction(project, element.getContainingFile()){
              @Override
              protected void run(final Result result) throws Throwable {
                final PsiClass psiClass = originalClasses.get(index);
                if (psiClass.isValid()) {
                  PsiDocumentManager.getInstance(project).commitAllDocuments();
                  referenceElement.bindToElement(psiClass);
                }
              }
            }.execute();
          }
        };
        final AsyncResult<DataContext> asyncResult = DataManager.getInstance().getDataContextFromFocus();
        asyncResult.doWhenDone(new Consumer<DataContext>() {
          @Override
          public void consume(DataContext dataContext) {
            new PopupChooserBuilder(list).
              setTitle(QuickFixBundle.message("add.qualifier.original.class.chooser.title")).
              setItemChoosenCallback(runnable).
              createPopup().
              showInBestPositionFor(dataContext);
          }
        });
      }
    }
  }
}
