/*
 * Copyright 2000-2015 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.vcs.log.ui.actions;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.JBPopupListener;
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.awt.*;
import java.util.Collection;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

public class FindPopupWithProgress {
  private static final Logger LOG = Logger.getInstance(FindPopupWithProgress.class);

  @NotNull private final TextFieldWithProgress myTextField;
  @NotNull private final Function<String, Future> myFunction;
  @NotNull private final JBPopup myPopup;
  @Nullable private Future myFuture;

  public FindPopupWithProgress(@NotNull final Project project,
                               @NotNull Collection<String> variants,
                               @NotNull Function<String, Future> function) {
    myFunction = function;
    myTextField = new TextFieldWithProgress(project, variants) {
      @Override
      public void onOk() {
        if (myFuture == null) {
          final Future future = myFunction.fun(getText().trim());
          myFuture = future;
          showProgress();
          ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
            @Override
            public void run() {
              try {
                future.get();
                okPopup();
              }
              catch (CancellationException ex) {
                cancelPopup();
              }
              catch (InterruptedException ex) {
                cancelPopup();
              }
              catch (ExecutionException ex) {
                LOG.error(ex);
                cancelPopup();
              }
            }
          });
        }
      }
    };

    myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(myTextField, myTextField.getPreferableFocusComponent())
      .setCancelOnClickOutside(true).setCancelOnWindowDeactivation(true).setCancelKeyEnabled(true).setRequestFocus(true).createPopup();
    myPopup.addListener(new JBPopupListener.Adapter() {
      @Override
      public void onClosed(LightweightWindowEvent event) {
        if (!event.isOk()) {
          if (myFuture != null) {
            myFuture.cancel(true);
          }
        }
        myFuture = null;
        myTextField.hideProgress();
      }
    });

    final JBTextField field = new JBTextField(20);
    final Dimension size = field.getPreferredSize();
    final Insets insets = myTextField.getBorder().getBorderInsets(myTextField);
    size.height += 6 + insets.top + insets.bottom;
    size.width += 4 + insets.left + insets.right;
    myPopup.setSize(size);
  }

  private void cancelPopup() {
    ApplicationManager.getApplication().invokeLater(new Runnable() {
      @Override
      public void run() {
        myPopup.cancel();
      }
    });
  }

  private void okPopup() {
    ApplicationManager.getApplication().invokeLater(new Runnable() {
      @Override
      public void run() {
        myPopup.closeOk(null);
      }
    });
  }

  public void showUnderneathOf(@NotNull Component anchor) {
    myPopup.showUnderneathOf(anchor);
  }
}

@@ -1038,25 +1038,21 @@
 nents.JB
-TextFi
+Lab
 el
-d
 ;%0Aimport
@@ -1076,24 +1076,60 @@
 l.Function;%0A
+import com.intellij.util.ui.UIUtil;%0A
 import org.j
@@ -1202,16 +1202,77 @@
 lable;%0A%0A
+import javax.swing.*;%0Aimport javax.swing.border.EmptyBorder;%0A
 import j
@@ -2868,16 +2868,485 @@
 %7D%0A    %7D;
+%0A    myTextField.setAlignmentX(Component.LEFT_ALIGNMENT);%0A%0A    JBLabel label = new JBLabel(%22Enter hash or branch/tag name:%22);%0A    label.setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD));%0A    label.setAlignmentX(Component.LEFT_ALIGNMENT);%0A%0A    JPanel panel = new JPanel();%0A    BoxLayout layout = new BoxLayout(panel, BoxLayout.PAGE_AXIS);%0A    panel.setLayout(layout);%0A    panel.add(label);%0A    panel.add(myTextField);%0A    panel.setBorder(new EmptyBorder(2, 2, 2, 2));
 %0A%0A    my
@@ -3410,27 +3410,21 @@
 Builder(
-myTextFi
+pan
 el
-d
 , myText
@@ -3927,321 +3927,8 @@
  %7D);
-%0A%0A    final JBTextField field = new JBTextField(20);%0A    final Dimension size = field.getPreferredSize();%0A    final Insets insets = myTextField.getBorder().getBorderInsets(myTextField);%0A    size.height += 6 + insets.top + insets.bottom;%0A    size.width += 4 + insets.left + insets.right;%0A    myPopup.setSize(size);
 %0A  %7D

add description in Go To Hash window