/*
 * 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 org.jetbrains.idea.svn.branchConfig;

import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.*;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.components.JBList;
import com.intellij.util.continuation.ModalityIgnorantBackgroundableTask;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.RootUrlInfo;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnFileUrlMapping;
import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * @author yole
 */
public class SelectBranchPopup {
  private final static String CONFIGURE_MESSAGE = SvnBundle.message("configure.branches.item");

  private SelectBranchPopup() {
  }

  public interface BranchSelectedCallback {
    void branchSelected(Project project, SvnBranchConfigurationNew configuration, String url, long revision);
  }

  public static void show(Project project, VirtualFile file, BranchSelectedCallback callback, final String title) {
    show(project, file, callback, title, null);
  }

  public static void show(Project project, VirtualFile file, BranchSelectedCallback callback, final String title, final Component component) {
    final SvnFileUrlMapping urlMapping = SvnVcs.getInstance(project).getSvnFileUrlMapping();
    final SVNURL svnurl = urlMapping.getUrlForFile(new File(file.getPath()));
    if (svnurl == null) {
      return;
    }
    final RootUrlInfo rootUrlInfo = urlMapping.getWcRootForUrl(svnurl.toString());
    if (rootUrlInfo == null) {
      return;
    }

    // not vcs root but wc root is ok
    showForBranchRoot(project, rootUrlInfo.getVirtualFile(), callback, title, component);
  }

  public static void showForBranchRoot(Project project, VirtualFile vcsRoot, BranchSelectedCallback callback, final String title) {
    showForBranchRoot(project, vcsRoot, callback, title, null);
  }

  public static void showForBranchRoot(Project project, VirtualFile vcsRoot, BranchSelectedCallback callback, final String title,
                                       final Component component) {
    final SvnBranchConfigurationNew configuration;
    try {
      configuration = SvnBranchConfigurationManager.getInstance(project).get(vcsRoot);
    }
    catch (VcsException e1) {
      Messages.showErrorDialog(project, SvnBundle.message("getting.branch.configuration.error", e1.getMessage()), title);
      return;
    }

    final List<String> items = new ArrayList<String>();
    if (! StringUtil.isEmptyOrSpaces(configuration.getTrunkUrl())) {
      items.add(getTrunkString(configuration));
    }
    for (String url : configuration.getBranchUrls()) {
      items.add(url);
    }
    items.add(CONFIGURE_MESSAGE);

    BranchBasesPopupStep step = new BranchBasesPopupStep(project, vcsRoot, configuration, callback, items, title, component);
    final ListPopup listPopup = JBPopupFactory.getInstance().createListPopup(step);
    step.showPopupAt(listPopup);
  }
  
  private static String getTrunkString(final SvnBranchConfigurationNew configuration) {
    return configuration.getTrunkUrl() + " (trunk)";
  }

  private static class BranchBasesPopupStep extends BaseListPopupStep<String> {
    protected final Project myProject;
    private final VirtualFile myVcsRoot;
    private final SvnBranchConfigurationNew myConfiguration;
    private final boolean myTopLevel;
    private BranchSelectedCallback myCallback;
    private final Component myComponent;

    private static final String REFRESH_MESSAGE = SvnBundle.message("refresh.branches.item");
    private String myTrunkString;

    protected BranchBasesPopupStep(final Project project,
                                   final VirtualFile vcsRoot,
                                   final SvnBranchConfigurationNew configuration,
                                   boolean topLevel,
                                   final BranchSelectedCallback callback,
                                   Component component) {
      myProject = project;
      myVcsRoot = vcsRoot;
      myConfiguration = configuration;
      myTrunkString = getTrunkString(configuration);
      myTopLevel = topLevel;
      myCallback = callback;
      myComponent = component;
    }

    public BranchBasesPopupStep(final Project project, final VirtualFile vcsRoot,
                                final SvnBranchConfigurationNew configuration,
                                final BranchSelectedCallback callback,
                                final List<String> items,
                                final String title,
                                Component component) {
      this(project, vcsRoot, configuration, true, callback, component);
      init(title, items, null);
    }

    @Override
    public ListSeparator getSeparatorAbove(final String value) {
      return (CONFIGURE_MESSAGE.equals(value)) ||
             (REFRESH_MESSAGE.equals(value)) ? new ListSeparator("") : null;
    }

    @NotNull
    @Override
    public String getTextFor(final String value) {
      int pos = value.lastIndexOf('/');
      if (pos < 0) {
        return value;
      }
      if (myTopLevel && ((myConfiguration.getTrunkUrl() == null) || (! value.startsWith(myConfiguration.getTrunkUrl())))) {
        return value.substring(pos+1) + "...";
      }
      return value.substring(pos+1);
    }

    @Override
    public boolean hasSubstep(final String selectedValue) {
      return false;
    }

    @Override
    public PopupStep onChosen(final String selectedValue, final boolean finalChoice) {
      if (CONFIGURE_MESSAGE.equals(selectedValue)) {
        return doFinalStep(new Runnable() {
          public void run() {
            BranchConfigurationDialog.configureBranches(myProject, myVcsRoot, true);
          }
        });
      }
      else if (myTrunkString.equals(selectedValue)) {
        return doFinalStep(new Runnable() {
          public void run() {
            myCallback.branchSelected(myProject, myConfiguration, myConfiguration.getTrunkUrl(), -1);
          }
        });
      }
      else if (!myTopLevel || selectedValue.equals(myConfiguration.getTrunkUrl())) {
        return doFinalStep(new Runnable() {
          public void run() {
            myCallback.branchSelected(myProject, myConfiguration, selectedValue, -1);
          }
        });
      }
      else {
        showBranchPopup(selectedValue);
      }
      return FINAL_CHOICE;
    }

    @Nullable
    private void loadBranches(final String selectedBranchesHolder, final Runnable runnable) {
      final ProgressManager pm = ProgressManager.getInstance();
      pm.run(new ModalityIgnorantBackgroundableTask(myProject, SvnBundle.message("compare.with.branch.progress.loading.branches")) {
        @Override
        protected void doInAwtIfFail(Exception e) {
          runnable.run();
        }

        @Override
        protected void doInAwtIfCancel() {
          runnable.run();
        }

        @Override
        protected void doInAwtIfSuccess() {
          runnable.run();
        }

        @Override
        protected void runImpl(@NotNull ProgressIndicator indicator) {
          final NewRootBunch manager = SvnBranchConfigurationManager.getInstance(myProject).getSvnBranchConfigManager();

          manager.reloadBranches(myVcsRoot, selectedBranchesHolder, InfoReliability.setByUser, false);
        }
      });
    }

    private void showBranchPopup(final String selectedValue) {
      List<SvnBranchItem> branches = myConfiguration.getBranches(selectedValue);
      if (branches == null) {
        return;
      }

      final Object[] items = new Object[branches.size() + 1];
      System.arraycopy(branches.toArray(), 0, items, 0, branches.size());
      items[items.length - 1] = REFRESH_MESSAGE;

      final JList branchList = new JBList(items);
      branchList.setCellRenderer(new BranchRenderer());
      final JBPopup popup = JBPopupFactory.getInstance().createListPopupBuilder(branchList)
        .setTitle(SVNPathUtil.tail(selectedValue))
        .setResizable(true)
        //.setDimensionServiceKey("Svn.CompareWithBranchPopup")
        .setItemChoosenCallback(new Runnable() {
          public void run() {
            if (REFRESH_MESSAGE.equals(branchList.getSelectedValue())) {
              SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                  loadBranches(selectedValue, new Runnable() {
                    @Override
                    public void run() {
                      showBranchPopup(selectedValue);
                    }
                  });
                }
              });
              return;
            }
            SvnBranchItem item = (SvnBranchItem)branchList.getSelectedValue();
            if (item != null) {
              myCallback.branchSelected(myProject, myConfiguration, item.getUrl(), item.getRevision());
            }
          }
        })
        .createPopup();
      showPopupAt(popup);
    }

    public void showPopupAt(final JBPopup listPopup) {
      if (myComponent == null) {
        listPopup.showCenteredInCurrentWindow(myProject);
      } else {
        listPopup.showInCenterOf(myComponent);
      }
    }
  }

  private static class BranchRenderer extends JPanel implements ListCellRenderer {
    private final JLabel myUrlLabel = new JLabel();
    private final JLabel myDateLabel = new JLabel();

    public BranchRenderer() {
      super(new BorderLayout());
      add(myUrlLabel, BorderLayout.WEST);
      add(myDateLabel, BorderLayout.EAST);
      myUrlLabel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
      myDateLabel.setHorizontalAlignment(JLabel.RIGHT);
      myDateLabel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
      myDateLabel.setForeground(UIUtil.getInactiveTextColor());
    }

    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
      if (isSelected || cellHasFocus) {
        setBackground(UIUtil.getListSelectionBackground());
        final Color selectedForegroundColor = UIUtil.getListSelectionForeground();
        myUrlLabel.setForeground(selectedForegroundColor);
        myDateLabel.setForeground(selectedForegroundColor);
        setForeground(selectedForegroundColor);
      }
      else {
        setBackground(UIUtil.getListBackground());
        final Color foregroundColor = UIUtil.getListForeground();
        myUrlLabel.setForeground(foregroundColor);
        myDateLabel.setForeground(UIUtil.getInactiveTextColor());
        setForeground(foregroundColor);
      }
      if (value instanceof String) {
        myUrlLabel.setText((String) value);
        myDateLabel.setText("");
      } else {
        SvnBranchItem item = (SvnBranchItem) value;
        myUrlLabel.setText(SVNPathUtil.tail(item.getUrl()));
        final long creationMillis = item.getCreationDateMillis();
        myDateLabel.setText((creationMillis > 0) ? DateFormatUtil.formatDate(creationMillis) : "");
      }
      return this;
    }
  }
}
