/*
 * Copyright 2000-2014 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.openapi.roots.libraries.ui.impl;

import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBoxTableRenderer;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.TitlePanel;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.*;
import com.intellij.ui.treeStructure.treetable.TreeColumnInfo;
import com.intellij.util.PlatformIcons;
import com.intellij.util.containers.Convertor;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ComboBoxCellEditor;
import com.intellij.util.ui.tree.TreeUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.io.File;
import java.util.*;
import java.util.List;

/**
 * This dialog allows selecting paths inside selected archives or directories.
 * The tree is three-level:
 * <ul>
 * <li>The root is a fake node that just holds child nodes.</li>
 * <li>The second level is archives or directories selected on the previous selection step.</li>
 * <li>The third level are detected roots inside previous selection.</li>
 * </ul>
 *
 * @author max
 * @author Constantine.Plotnikov
 */
public class DetectedRootsChooserDialog extends DialogWrapper {
  private static final ColumnInfo ROOT_COLUMN = new TreeColumnInfo("");
  private static final ColumnInfo<VirtualFileCheckedTreeNode, String> ROOT_TYPE_COLUMN = new ColumnInfo<VirtualFileCheckedTreeNode, String>("") {
    @Override
    public String valueOf(VirtualFileCheckedTreeNode node) {
      final SuggestedChildRootInfo rootInfo = node.getRootInfo();
      return rootInfo != null ? rootInfo.getRootTypeName(rootInfo.getSelectedRootType()) : "";
    }

    @Override
    public TableCellRenderer getRenderer(VirtualFileCheckedTreeNode node) {
      final SuggestedChildRootInfo rootInfo = node.getRootInfo();
      if (rootInfo != null && isCellEditable(node)) {
        return new ComboBoxTableRenderer<String>(rootInfo.getRootTypeNames());
      }
      return new DefaultTableCellRenderer();
    }

    @Override
    public TableCellEditor getEditor(VirtualFileCheckedTreeNode o) {
      final SuggestedChildRootInfo rootInfo = o.getRootInfo();
      if (rootInfo == null) return null;
      final ComboBoxCellEditor editor = new ComboBoxCellEditor() {
        @Override
        protected List<String> getComboBoxItems() {
          return Arrays.asList(rootInfo.getRootTypeNames());
        }
      };
      editor.setClickCountToStart(1);
      return editor;
    }

    @Override
    public boolean isCellEditable(VirtualFileCheckedTreeNode node) {
      final SuggestedChildRootInfo rootInfo = node.getRootInfo();
      return rootInfo != null && rootInfo.getDetectedRoot().getTypes().size() > 1;
    }

    @Override
    public void setValue(VirtualFileCheckedTreeNode node, String value) {
      final SuggestedChildRootInfo rootInfo = node.getRootInfo();
      if (rootInfo != null) {
        rootInfo.setSelectedRootType(value);
      }
    }
  };

  private CheckboxTreeTable myTreeTable;
  private JScrollPane myPane;
  private String myDescription;

  public DetectedRootsChooserDialog(Component component, Collection<SuggestedChildRootInfo> suggestedRoots) {
    super(component, true);
    init(suggestedRoots);
  }

  public DetectedRootsChooserDialog(Project project, Collection<SuggestedChildRootInfo> suggestedRoots) {
    super(project, true);
    init(suggestedRoots);
  }

  private void init(Collection<SuggestedChildRootInfo> suggestedRoots) {
    myDescription = XmlStringUtil.wrapInHtml(ApplicationNamesInfo.getInstance().getFullProductName() +
                    " just scanned files and detected the following " + StringUtil.pluralize("root", suggestedRoots.size()) + ".<br>" +
                    "Select items in the tree below or press Cancel to cancel operation.");
    myTreeTable = createTreeTable(suggestedRoots);
    myPane = ScrollPaneFactory.createScrollPane(myTreeTable);
    setTitle("Detected Roots");
    init();
  }

  private static CheckboxTreeTable createTreeTable(Collection<SuggestedChildRootInfo> suggestedRoots) {
    final CheckedTreeNode root = createRoot(suggestedRoots);
    CheckboxTreeTable treeTable = new CheckboxTreeTable(root, new CheckboxTree.CheckboxTreeCellRenderer(true) {
      @Override
      public void customizeRenderer(JTree tree,
                                        Object value,
                                        boolean selected,
                                        boolean expanded,
                                        boolean leaf,
                                        int row,
                                        boolean hasFocus) {
        if (!(value instanceof VirtualFileCheckedTreeNode)) return;
        VirtualFileCheckedTreeNode node = (VirtualFileCheckedTreeNode)value;
        VirtualFile file = node.getFile();
        String text;
        SimpleTextAttributes attributes;
        Icon icon;
        boolean isValid = true;
        if (leaf) {
          VirtualFile ancestor = ((VirtualFileCheckedTreeNode)node.getParent()).getFile();
          if (ancestor != null) {
            text = VfsUtilCore.getRelativePath(file, ancestor, File.separatorChar);
            if (StringUtil.isEmpty(text)) {
              text = File.separator;
            }
          }
          else {
            text = file.getPresentableUrl();
          }
          if (text == null) {
            isValid = false;
            text = file.getPresentableUrl();
          }
          attributes = SimpleTextAttributes.REGULAR_ATTRIBUTES;
          icon = PlatformIcons.DIRECTORY_CLOSED_ICON;
        }
        else {
          text = file.getPresentableUrl();
          attributes = SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES;
          icon = PlatformIcons.DIRECTORY_CLOSED_ICON;
        }
        final ColoredTreeCellRenderer textRenderer = getTextRenderer();
        textRenderer.setIcon(icon);
        if (!isValid) {
          textRenderer.append("[INVALID] ", SimpleTextAttributes.ERROR_ATTRIBUTES);
        }
        textRenderer.append(text, attributes);
      }
    }, new ColumnInfo[]{ROOT_COLUMN, ROOT_TYPE_COLUMN});

    int max = 0;
    for (SuggestedChildRootInfo info : suggestedRoots) {
      for (String s : info.getRootTypeNames()) {
        max = Math.max(max, treeTable.getFontMetrics(treeTable.getFont()).stringWidth(s));
      }
    }
    final TableColumn column = treeTable.getColumnModel().getColumn(1);
    int width = max + 20;//add space for combobox button
    column.setPreferredWidth(width);
    column.setMaxWidth(width);
    treeTable.setRootVisible(false);
    new TreeTableSpeedSearch(treeTable, new Convertor<TreePath, String>() {
      @Override
      public String convert(TreePath o) {
        Object node = o.getLastPathComponent();
        if (!(node instanceof VirtualFileCheckedTreeNode)) return "";
        return ((VirtualFileCheckedTreeNode)node).getFile().getPresentableUrl();
      }
    });
    TreeUtil.expandAll(treeTable.getTree());
    return treeTable;
  }

  private static CheckedTreeNode createRoot(Collection<SuggestedChildRootInfo> suggestedRoots) {
    SuggestedChildRootInfo[] sortedRoots = suggestedRoots.toArray(new SuggestedChildRootInfo[suggestedRoots.size()]);
    Arrays.sort(sortedRoots, new Comparator<SuggestedChildRootInfo>() {
      @Override
      public int compare(@NotNull SuggestedChildRootInfo o1, @NotNull SuggestedChildRootInfo o2) {
        return o1.getDetectedRoot().getFile().getPresentableUrl().compareTo(o2.getDetectedRoot().getFile().getPresentableUrl());
      }
    });

    CheckedTreeNode root = new CheckedTreeNode(null);
    Map<VirtualFile, CheckedTreeNode> rootCandidateNodes = new HashMap<VirtualFile, CheckedTreeNode>();
    for (SuggestedChildRootInfo rootInfo : sortedRoots) {
      final VirtualFile rootCandidate = rootInfo.getRootCandidate();
      CheckedTreeNode parent = rootCandidateNodes.get(rootCandidate);
      if (parent == null) {
        parent = new VirtualFileCheckedTreeNode(rootCandidate);
        rootCandidateNodes.put(rootCandidate, parent);
        root.add(parent);
      }
      parent.add(new VirtualFileCheckedTreeNode(rootInfo));
    }
    return root;
  }

  @Override
  protected JComponent createTitlePane() {
    return new TitlePanel("Choose Roots", myDescription);
  }

  @Nullable
  @Override
  protected JComponent createCenterPanel() {
    return myPane;
  }

  public SuggestedChildRootInfo[] getChosenRoots() {
    return myTreeTable.getCheckedNodes(SuggestedChildRootInfo.class);
  }

  @NonNls
  @Override
  protected String getDimensionServiceKey() {
    return "DetectedRootsChooserDialog";
  }

  @Nullable
  @Override
  public JComponent getPreferredFocusedComponent() {
    return myTreeTable;
  }

  private static class VirtualFileCheckedTreeNode extends CheckedTreeNode {
    private final VirtualFile myFile;

    private VirtualFileCheckedTreeNode(VirtualFile file) {
      super(file);
      myFile = file;
    }

    public VirtualFileCheckedTreeNode(SuggestedChildRootInfo rootInfo) {
      super(rootInfo);
      myFile = rootInfo.getDetectedRoot().getFile();
    }

    public VirtualFile getFile() {
      return myFile;
    }

    @Nullable
    private SuggestedChildRootInfo getRootInfo() {
      return userObject instanceof SuggestedChildRootInfo ? (SuggestedChildRootInfo)userObject : null;
    }
  }
}
