/*
 * 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.codeInsight.lookup.impl;

import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.ui.ListScrollingUtil;

/**
 * @author yole
 */
public abstract class LookupActionHandler extends EditorActionHandler {
  protected final EditorActionHandler myOriginalHandler;
  private final boolean myRequireFocusedLookup;

  public LookupActionHandler(EditorActionHandler originalHandler, boolean requireFocusedLookup) {
    myOriginalHandler = originalHandler;
    myRequireFocusedLookup = requireFocusedLookup;
  }

  @Override
  public boolean executeInCommand(Editor editor, DataContext dataContext) {
    return LookupManager.getActiveLookup(editor) == null;
  }

  public void execute(Editor editor, DataContext dataContext){
    LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
    if (lookup == null || myRequireFocusedLookup && !lookup.isFocused()) {
      LookupManager.getInstance(editor.getProject()).hideActiveLookup();
      myOriginalHandler.execute(editor, dataContext);
      return;
    }

    lookup.markDirty();
    executeInLookup(lookup);
  }

  protected abstract void executeInLookup(LookupImpl lookup);

  public boolean isEnabled(Editor editor, DataContext dataContext) {
    LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
    return lookup != null || myOriginalHandler.isEnabled(editor, dataContext);
  }

  public static class DownHandler extends LookupActionHandler {

    public DownHandler(EditorActionHandler originalHandler){
      super(originalHandler, false);
    }

    protected void executeInLookup(final LookupImpl lookup) {
      if (!lookup.isFocused()) {
        lookup.setFocused(true);
        lookup.getList().setSelectedIndex(0);
        lookup.refreshUi();
      } else {
        ListScrollingUtil.moveDown(lookup.getList(), 0);
      }
    }
  }

  public static class UpHandler extends LookupActionHandler {
    public UpHandler(EditorActionHandler originalHandler){
      super(originalHandler, false);
    }

    @Override
    public boolean isEnabled(Editor editor, DataContext dataContext) {
      return super.isEnabled(editor, dataContext) && UISettings.getInstance().CYCLE_SCROLLING;
    }

    protected void executeInLookup(final LookupImpl lookup) {
      if (!lookup.isFocused()) {
        lookup.setFocused(true);
        lookup.getList().setSelectedIndex(0);
        lookup.refreshUi();
      }
      ListScrollingUtil.moveUp(lookup.getList(), 0);
    }
  }

  public static class PageDownHandler extends LookupActionHandler {
    public PageDownHandler(final EditorActionHandler originalHandler) {
      super(originalHandler, true);
    }

    protected void executeInLookup(final LookupImpl lookup) {
      ListScrollingUtil.movePageDown(lookup.getList());
    }
  }

  public static class PageUpHandler extends LookupActionHandler {
    public PageUpHandler(EditorActionHandler originalHandler){
      super(originalHandler, true);
    }

    protected void executeInLookup(final LookupImpl lookup) {
      ListScrollingUtil.movePageUp(lookup.getList());
    }
  }

}

@@ -897,24 +897,69 @@
 ionHandler;%0A
+import com.intellij.openapi.project.Project;%0A
 import com.i
@@ -1746,24 +1746,100 @@
 ocused()) %7B%0A
+      Project project = editor.getProject();%0A      if (project != null) %7B%0A  
       Lookup
@@ -1858,35 +1858,23 @@
 nstance(
-editor.getP
+p
 roject
-()
 ).hideAc
@@ -1883,24 +1883,32 @@
 veLookup();%0A
+      %7D%0A
       myOrig

fix NPE in editing tests