/*
 * 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 org.jetbrains.idea.maven.wizards;

import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.wizard.StepAdapter;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.*;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.containers.Convertor;
import com.intellij.util.ui.AsyncProcessIcon;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.indices.MavenIndicesManager;
import org.jetbrains.idea.maven.model.MavenArchetype;

import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.*;
import java.util.List;

/**
 * @author Dmitry Avdeev
 *         Date: 24.09.13
 */
public class MavenArchetypesStep extends ModuleWizardStep implements Disposable {

  private JCheckBox myUseArchetypeCheckBox;
  private JButton myAddArchetypeButton;
  private JPanel myArchetypesPanel;
  private final Tree myArchetypesTree;
  private JScrollPane myArchetypeDescriptionScrollPane;
  private JPanel myMainPanel;
  private JTextArea myArchetypeDescriptionField;

  private Object myCurrentUpdaterMarker;
  private final AsyncProcessIcon myLoadingIcon = new AsyncProcessIcon.Big(getClass() + ".loading");

  private boolean skipUpdateUI;
  private final MavenModuleBuilder myBuilder;
  @Nullable private final StepAdapter myStep;

  public MavenArchetypesStep(MavenModuleBuilder builder, @Nullable StepAdapter step) {
    myBuilder = builder;
    myStep = step;
    Disposer.register(this, myLoadingIcon);

    myArchetypesTree = new Tree();
    myArchetypesTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
    JScrollPane archetypesScrollPane = ScrollPaneFactory.createScrollPane(myArchetypesTree);

    myArchetypesPanel.add(archetypesScrollPane, "archetypes");

    JPanel loadingPanel = new JPanel(new GridBagLayout());
    JPanel bp = new JPanel(new BorderLayout(10, 10));
    bp.add(new JLabel("Loading archetype list..."), BorderLayout.NORTH);
    bp.add(myLoadingIcon, BorderLayout.CENTER);

    loadingPanel.add(bp, new GridBagConstraints());

    myArchetypesPanel.add(ScrollPaneFactory.createScrollPane(loadingPanel), "loading");
    ((CardLayout)myArchetypesPanel.getLayout()).show(myArchetypesPanel, "archetypes");


    myUseArchetypeCheckBox.addItemListener(new ItemListener() {
      @Override
      public void itemStateChanged(ItemEvent e) {
        updateComponents();
        archetypeMayBeChanged();
      }
    });

    myAddArchetypeButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        doAddArchetype();
      }
    });

    myArchetypesTree.setRootVisible(false);
    myArchetypesTree.setShowsRootHandles(true);
    myArchetypesTree.setCellRenderer(new MyRenderer());
    myArchetypesTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

    myArchetypesTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent e) {
        updateArchetypeDescription();
        archetypeMayBeChanged();
      }
    });

    new TreeSpeedSearch(myArchetypesTree, new Convertor<TreePath, String>() {
      public String convert(TreePath path) {
        MavenArchetype info = getArchetypeInfoFromPathComponent(path.getLastPathComponent());
        return info.groupId + ":" + info.artifactId + ":" + info.version;
      }
    }).setComparator(new SpeedSearchComparator(false));

    myArchetypeDescriptionField.setEditable(false);
    myArchetypeDescriptionField.setBackground(UIUtil.getPanelBackground());

    requestUpdate();
    updateComponents();
  }

  public JPanel getMainPanel() {
    return myMainPanel;
  }

  private void updateComponents() {
    boolean archetypesEnabled = myUseArchetypeCheckBox.isSelected();
    myAddArchetypeButton.setEnabled(archetypesEnabled);
    myArchetypesTree.setEnabled(archetypesEnabled);
    myArchetypesTree.setBackground(archetypesEnabled ? UIUtil.getListBackground() : UIUtil.getPanelBackground());

  }

  @Nullable
  public MavenArchetype getSelectedArchetype() {
    if (!myUseArchetypeCheckBox.isSelected() || myArchetypesTree.isSelectionEmpty()) return null;
    return getArchetypeInfoFromPathComponent(myArchetypesTree.getLastSelectedPathComponent());
  }

  private static MavenArchetype getArchetypeInfoFromPathComponent(Object sel) {
    return (MavenArchetype)((DefaultMutableTreeNode)sel).getUserObject();
  }

  private void updateArchetypeDescription() {
    MavenArchetype sel = getSelectedArchetype();
    String desc = sel == null ? null : sel.description;
    if (StringUtil.isEmptyOrSpaces(desc)) {
      myArchetypeDescriptionScrollPane.setVisible(false);
    }
    else {
      myArchetypeDescriptionScrollPane.setVisible(true);
      myArchetypeDescriptionField.setText(desc);
    }
  }

  @Nullable
  private static TreePath findNodePath(MavenArchetype object, TreeModel model, Object parent) {
    for (int i = 0; i < model.getChildCount(parent); i++) {
      DefaultMutableTreeNode each = (DefaultMutableTreeNode)model.getChild(parent, i);
      if (each.getUserObject().equals(object)) return new TreePath(each.getPath());

      TreePath result = findNodePath(object, model, each);
      if (result != null) return result;
    }
    return null;
  }

  private static TreeNode groupAndSortArchetypes(Set<MavenArchetype> archetypes) {
    List<MavenArchetype> list = new ArrayList<MavenArchetype>(archetypes);

    Collections.sort(list, new Comparator<MavenArchetype>() {
      public int compare(MavenArchetype o1, MavenArchetype o2) {
        String key1 = o1.groupId + ":" + o1.artifactId;
        String key2 = o2.groupId + ":" + o2.artifactId;

        int result = key1.compareToIgnoreCase(key2);
        if (result != 0) return result;

        return o2.version.compareToIgnoreCase(o1.version);
      }
    });

    Map<String, List<MavenArchetype>> map = new TreeMap<String, List<MavenArchetype>>();

    for (MavenArchetype each : list) {
      String key = each.groupId + ":" + each.artifactId;
      List<MavenArchetype> versions = map.get(key);
      if (versions == null) {
        versions = new ArrayList<MavenArchetype>();
        map.put(key, versions);
      }
      versions.add(each);
    }

    DefaultMutableTreeNode result = new DefaultMutableTreeNode("root", true);
    for (List<MavenArchetype> each : map.values()) {
      MavenArchetype eachArchetype = each.get(0);
      DefaultMutableTreeNode node = new DefaultMutableTreeNode(eachArchetype, true);
      for (MavenArchetype eachVersion : each) {
        DefaultMutableTreeNode versionNode = new DefaultMutableTreeNode(eachVersion, false);
        node.add(versionNode);
      }
      result.add(node);
    }

    return result;
  }

  public void requestUpdate() {

    MavenArchetype selectedArch = getSelectedArchetype();
    if (selectedArch == null) {
      selectedArch = myBuilder.getArchetype();
    }
    if (selectedArch != null) myUseArchetypeCheckBox.setSelected(true);

    if (myArchetypesTree.getRowCount() == 0) updateArchetypesList(selectedArch);
  }

  public void updateArchetypesList(final MavenArchetype selected) {
    ApplicationManager.getApplication().assertIsDispatchThread();

    myLoadingIcon.setBackground(myArchetypesTree.getBackground());

    ((CardLayout)myArchetypesPanel.getLayout()).show(myArchetypesPanel, "loading");

    final Object currentUpdaterMarker = new Object();
    myCurrentUpdaterMarker = currentUpdaterMarker;

    ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
      public void run() {
        final Set<MavenArchetype> archetypes = MavenIndicesManager.getInstance().getArchetypes();

        //noinspection SSBasedInspection
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            if (currentUpdaterMarker != myCurrentUpdaterMarker) return; // Other updater has been run.

            ((CardLayout)myArchetypesPanel.getLayout()).show(myArchetypesPanel, "archetypes");

            TreeNode root = groupAndSortArchetypes(archetypes);
            TreeModel model = new DefaultTreeModel(root);
            myArchetypesTree.setModel(model);

            if (selected != null) {
              TreePath path = findNodePath(selected, model, model.getRoot());
              if (path != null) {
                myArchetypesTree.expandPath(path.getParentPath());
                TreeUtil.selectPath(myArchetypesTree, path, true);
              }
            }

            updateArchetypeDescription();
          }
        });
      }
    });
  }

  public boolean isSkipUpdateUI() {
    return skipUpdateUI;
  }

  private void archetypeMayBeChanged() {
    MavenArchetype selectedArchetype = getSelectedArchetype();
    if (((myBuilder.getArchetype() == null) != (selectedArchetype == null))) {
      myBuilder.setArchetype(selectedArchetype);
      skipUpdateUI = true;
      try {
        if (myStep != null) {
          myStep.fireStateChanged();
        }
      }
      finally {
        skipUpdateUI = false;
      }
    }
  }


  private void doAddArchetype() {
    MavenAddArchetypeDialog dialog = new MavenAddArchetypeDialog(myMainPanel);
    dialog.show();
    if (!dialog.isOK()) return;

    MavenArchetype archetype = dialog.getArchetype();
    MavenIndicesManager.getInstance().addArchetype(archetype);
    updateArchetypesList(archetype);
  }

  @Override
  public void dispose() {
  }

  @Override
  public JComponent getComponent() {
    return getMainPanel();
  }

  @Override
  public void updateDataModel() {
    MavenArchetype selectedArchetype = getSelectedArchetype();
    myBuilder.setArchetype(selectedArchetype);
  }

  private static class MyRenderer extends ColoredTreeCellRenderer {
    public void customizeCellRenderer(JTree tree,
                                      Object value,
                                      boolean selected,
                                      boolean expanded,
                                      boolean leaf,
                                      int row,
                                      boolean hasFocus) {
      Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
      if (!(userObject instanceof MavenArchetype)) return;

      MavenArchetype info = (MavenArchetype)userObject;

      if (leaf) {
        append(info.artifactId, SimpleTextAttributes.GRAY_ATTRIBUTES);
        append(":" + info.version, SimpleTextAttributes.REGULAR_ATTRIBUTES);
      }
      else {
        append(info.groupId + ":", SimpleTextAttributes.GRAY_ATTRIBUTES);
        append(info.artifactId, SimpleTextAttributes.REGULAR_ATTRIBUTES);
      }
    }
  }

}
