/*
 * Copyright 2000-2009 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.uiDesigner.actions;

import com.intellij.CommonBundle;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.uiDesigner.FormEditingUtil;
import com.intellij.uiDesigner.UIDesignerBundle;
import com.intellij.uiDesigner.designSurface.GuiEditor;
import com.intellij.uiDesigner.propertyInspector.properties.BindingProperty;
import com.intellij.uiDesigner.radComponents.RadComponent;
import com.intellij.uiDesigner.radComponents.RadRootContainer;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.beans.BeanInfo;
import java.beans.EventSetDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * @author yole
 */
public class CreateListenerAction extends AbstractGuiEditorAction {
  private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.actions.CreateListenerAction");

  protected void actionPerformed(final GuiEditor editor, final List<RadComponent> selection, final AnActionEvent e) {
    final DefaultActionGroup actionGroup = prepareActionGroup(selection);
    final JComponent selectedComponent = selection.get(0).getDelegee();
    final DataContext context = DataManager.getInstance().getDataContext(selectedComponent);
    final JBPopupFactory factory = JBPopupFactory.getInstance();
    final ListPopup popup = factory.createActionGroupPopup(UIDesignerBundle.message("create.listener.title"), actionGroup, context,
                                                           JBPopupFactory.ActionSelectionAid.NUMBERING, true);

    FormEditingUtil.showPopupUnderComponent(popup, selection.get(0));
  }

  private DefaultActionGroup prepareActionGroup(final List<RadComponent> selection) {
    final DefaultActionGroup actionGroup = new DefaultActionGroup();
    final EventSetDescriptor[] eventSetDescriptors;
    try {
      BeanInfo beanInfo = Introspector.getBeanInfo(selection.get(0).getComponentClass());
      eventSetDescriptors = beanInfo.getEventSetDescriptors();
    }
    catch (IntrospectionException e) {
      LOG.error(e);
      return null;
    }
    EventSetDescriptor[] sortedDescriptors = new EventSetDescriptor[eventSetDescriptors.length];
    System.arraycopy(eventSetDescriptors, 0, sortedDescriptors, 0, eventSetDescriptors.length);
    Arrays.sort(sortedDescriptors, new Comparator<EventSetDescriptor>() {
      public int compare(final EventSetDescriptor o1, final EventSetDescriptor o2) {
        return o1.getListenerType().getName().compareTo(o2.getListenerType().getName());
      }
    });
    for(EventSetDescriptor descriptor: sortedDescriptors) {
      actionGroup.add(new MyCreateListenerAction(selection, descriptor));
    }
    return actionGroup;
  }

  @Override
  protected void update(@NotNull GuiEditor editor, final ArrayList<RadComponent> selection, final AnActionEvent e) {
    e.getPresentation().setEnabled(canCreateListener(selection));
  }

  private static boolean canCreateListener(final ArrayList<RadComponent> selection) {
    if (selection.size() == 0) return false;
    final RadRootContainer root = (RadRootContainer)FormEditingUtil.getRoot(selection.get(0));
    if (root.getClassToBind() == null) return false;
    String componentClass = selection.get(0).getComponentClassName();
    for(RadComponent c: selection) {
      if (!c.getComponentClassName().equals(componentClass) || c.getBinding() == null) return false;
      if (BindingProperty.findBoundField(root, c.getBinding()) == null) return false;
    }
    return true;
  }

  private class MyCreateListenerAction extends AnAction {
    private final List<RadComponent> mySelection;
    private final EventSetDescriptor myDescriptor;
    @NonNls private static final String LISTENER_SUFFIX = "Listener";
    @NonNls private static final String ADAPTER_SUFFIX = "Adapter";

    public MyCreateListenerAction(final List<RadComponent> selection, EventSetDescriptor descriptor) {
      super(descriptor.getListenerType().getSimpleName());
      mySelection = selection;
      myDescriptor = descriptor;
    }

    public void actionPerformed(AnActionEvent e) {
      CommandProcessor.getInstance().executeCommand(
        mySelection.get(0).getProject(),
        new Runnable() {
          public void run() {
            ApplicationManager.getApplication().runWriteAction(new Runnable() {
              public void run() {
                createListener();
              }
            });
          }
        }, UIDesignerBundle.message("create.listener.command"), null
      );
    }

    private void createListener() {
      RadRootContainer root = (RadRootContainer)FormEditingUtil.getRoot(mySelection.get(0));
      final PsiField[] boundFields = new PsiField[mySelection.size()];
      for (int i = 0; i < mySelection.size(); i++) {
        boundFields[i] = BindingProperty.findBoundField(root, mySelection.get(i).getBinding());
      }
      final PsiClass myClass = boundFields[0].getContainingClass();

      if (!FileModificationService.getInstance().preparePsiElementForWrite(myClass)) return;

      try {
        PsiMethod constructor = findConstructorToInsert(myClass);
        final Module module = ModuleUtil.findModuleForPsiElement(myClass);
        PsiClass listenerClass = null;
        final String listenerClassName = myDescriptor.getListenerType().getName();
        if (listenerClassName.endsWith(LISTENER_SUFFIX)) {
          String adapterClassName = listenerClassName.substring(0, listenerClassName.length() - LISTENER_SUFFIX.length()) + ADAPTER_SUFFIX;
          listenerClass = JavaPsiFacade.getInstance(myClass.getProject())
            .findClass(adapterClassName, GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module));
        }
        if (listenerClass == null) {
          listenerClass = JavaPsiFacade.getInstance(myClass.getProject())
            .findClass(listenerClassName, GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module));
        }
        if (listenerClass == null) {
          Messages.showErrorDialog(myClass.getProject(), UIDesignerBundle.message("create.listener.class.not.found"), CommonBundle.getErrorTitle());
          return;
        }

        PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory();
        final PsiCodeBlock body = constructor.getBody();
        LOG.assertTrue(body != null);

        @NonNls StringBuilder builder = new StringBuilder();
        @NonNls String variableName = null;
        if (boundFields.length == 1) {
          builder.append(boundFields[0].getName());
          builder.append(".");
          builder.append(myDescriptor.getAddListenerMethod().getName());
          builder.append("(");
        }
        else {
          builder.append(listenerClass.getQualifiedName()).append(" ");
          if (body.getLastBodyElement() == null) {
            variableName = "listener";
          }
          else {
            final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(myClass.getProject());
            variableName = codeStyleManager.suggestUniqueVariableName("listener", body.getLastBodyElement(), false);
          }
          builder.append(variableName).append("=");
        }
        builder.append("new ");
        builder.append(listenerClass.getQualifiedName());
        builder.append("() { } ");
        if (boundFields.length == 1) {
          builder.append(");");
        }
        else {
          builder.append(";");
        }

        PsiStatement stmt = factory.createStatementFromText(builder.toString(), constructor);
        stmt = (PsiStatement)body.addAfter(stmt, body.getLastBodyElement());
        JavaCodeStyleManager.getInstance(body.getProject()).shortenClassReferences(stmt);

        if (boundFields.length > 1) {
          PsiElement anchor = stmt;
          for (PsiField field : boundFields) {
            PsiElement addStmt = factory
              .createStatementFromText(field.getName() + "." + myDescriptor.getAddListenerMethod().getName() + "(" + variableName + ");",
                                       constructor);
            addStmt = body.addAfter(addStmt, anchor);
            anchor = addStmt;
          }
        }

        final Ref<PsiClass> newClassRef = new Ref<PsiClass>();
        stmt.accept(new JavaRecursiveElementWalkingVisitor() {
          @Override
          public void visitClass(PsiClass aClass) {
            newClassRef.set(aClass);
          }
        });
        final PsiClass newClass = newClassRef.get();
        final SmartPsiElementPointer ptr = SmartPointerManager.getInstance(myClass.getProject()).createSmartPsiElementPointer(newClass);
        final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(newClass);
        final FileEditor[] fileEditors =
          virtualFile != null ? FileEditorManager.getInstance(newClass.getProject()).openFile(virtualFile, true, true) : null;
        IdeFocusManager.findInstance().doWhenFocusSettlesDown(new Runnable() {
          public void run() {
            final PsiClass newClass = (PsiClass)ptr.getElement();
            final Editor editor = getEditor();
            if (editor != null && newClass != null) {
              CommandProcessor.getInstance().executeCommand(myClass.getProject(), new Runnable() {
                public void run() {
                  if (!OverrideImplementExploreUtil.getMethodSignaturesToImplement(newClass).isEmpty()) {
                    OverrideImplementUtil.chooseAndImplementMethods(newClass.getProject(), editor, newClass);
                  }
                  else {
                    OverrideImplementUtil.chooseAndOverrideMethods(newClass.getProject(), editor, newClass);
                  }
                }
              }, "", null);
            }
          }

          private Editor getEditor() {
            if (fileEditors != null) {
              for (FileEditor fileEditor : fileEditors) {
                if (fileEditor instanceof TextEditor) {
                  return ((TextEditor)fileEditor).getEditor();
                }
              }
            }
            return null;
          }
        });
      }
      catch (IncorrectOperationException ex) {
        LOG.error(ex);
      }
    }

    private PsiMethod findConstructorToInsert(final PsiClass aClass) throws IncorrectOperationException {
      final PsiMethod[] constructors = aClass.getConstructors();
      if (constructors.length == 0) {
        PsiElementFactory factory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory();
        PsiMethod newConstructor = factory.createMethodFromText("public " + aClass.getName() + "() { }", aClass);
        final PsiMethod[] psiMethods = aClass.getMethods();
        PsiMethod firstMethod = (psiMethods.length == 0) ? null : psiMethods [0];
        return (PsiMethod) aClass.addBefore(newConstructor, firstMethod);
      }
      for(PsiMethod method: constructors) {
        if (method.getParameterList().getParametersCount() == 0) {
          return method;
        }
      }
      return constructors [0];
    }
  }
}
