/*
 * Copyright 2000-2010 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.
 */

/*
 * @author max
 */
package com.intellij.openapi.ui;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonShortcuts;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.UnnamedConfigurable;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.util.*;
import com.intellij.util.IconUtil;
import com.intellij.util.ui.tree.TreeUtil;
import gnu.trove.Equality;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public abstract class NamedItemsListEditor<T> extends MasterDetailsComponent {
    private final Namer<T> myNamer;
    private final Factory<T> myFactory;
    private final Cloner<T> myCloner;
    private final List<T> myItems = new ArrayList<T>();
    private final Equality<T> myComparer;
    private List<T> myResultItems;
    private final List<T> myOriginalItems;
    private boolean myShowIcons;

    protected NamedItemsListEditor(Namer<T> namer,
                                   Factory<T> factory,
                                   Cloner<T> cloner,
                                   Equality<T> comparer,
                                   List<T> items) {
      this(namer, factory, cloner, comparer, items, true);
    }

    protected NamedItemsListEditor(Namer<T> namer,
                                   Factory<T> factory,
                                   Cloner<T> cloner,
                                   Equality<T> comparer,
                                   List<T> items,
                                   boolean initInConstructor) {
        myNamer = namer;
        myFactory = factory;
        myCloner = cloner;
        myComparer = comparer;

        myOriginalItems = items;
        myResultItems = items;
        if (initInConstructor) {
          reset();
          initTree();
        }
    }

    @Override
    public void reset() {
        myResultItems = myOriginalItems;
        myItems.clear();

        clearChildren();
        for (T item : myOriginalItems) {
            addNewNode(myCloner.cloneOf(item));
        }

        super.reset();
    }

    @Override
    protected void processRemovedItems() {
    }

    @Override
    protected boolean wasObjectStored(Object editableObject) {
        return true;
    }

    protected String subjDisplayName() {
        return "item";
    }

    @Nullable
    public String askForProfileName(String titlePattern) {
        String title = MessageFormat.format(titlePattern, subjDisplayName());
        return Messages.showInputDialog("New " + subjDisplayName() + " name:", title, Messages.getQuestionIcon(), "", new InputValidator() {
            @Override
            public boolean checkInput(String s) {
                return s.length() > 0 && findByName(s) == null;
            }

            @Override
            public boolean canClose(String s) {
                return checkInput(s);
            }
        });
    }

    @Nullable
    private T findByName(String name) {
        for (T item : myItems) {
            if (Comparing.equal(name, myNamer.getName(item))) return item;
        }

        return null;
    }

    @Override
    @Nullable
    protected ArrayList<AnAction> createActions(boolean fromPopup) {
        ArrayList<AnAction> result = new ArrayList<AnAction>();
        result.add(new AddAction());

        result.add(new MyDeleteAction(forAll(new Condition<Object>() {
            @Override
            @SuppressWarnings({"unchecked"})
            public boolean value(Object o) {
                return canDelete((T) ((MyNode) o).getConfigurable().getEditableObject());
            }
        })));

        result.add(new CopyAction());

        return result;
    }

    private void addNewNode(T item) {
        addNode(new MyNode(new ItemConfigurable(item)), myRoot);
        myItems.add(item);
    }

    protected boolean canDelete(T item) {
        return true;
    }

    protected abstract UnnamedConfigurable createConfigurable(T item);

    @Override
    protected void onItemDeleted(Object item) {
      //noinspection unchecked
      myItems.remove((T)item);
    }

    protected void setDisplayName(T item, String name) {
      myNamer.setName(item, name);
    }

    public void setShowIcons(boolean showIcons) {
      myShowIcons = showIcons;
    }

    @Nullable
    protected UnnamedConfigurable getItemConfigurable(final T item) {
      final Ref<UnnamedConfigurable> result = new Ref<UnnamedConfigurable>();
      TreeUtil.traverse((TreeNode)myTree.getModel().getRoot(), new TreeUtil.Traverse() {
        @Override
        public boolean accept(Object node) {
          final NamedConfigurable configurable = (NamedConfigurable)((DefaultMutableTreeNode)node).getUserObject();
          if (configurable.getEditableObject() == item) {
            //noinspection unchecked
            result.set(((ItemConfigurable)configurable).myConfigurable);
            return false;
          }
          else {
            return true;
          }
        }
      });
      return result.get();
    }

  @Override
  public void disposeUIResources() {
    super.disposeUIResources();    //To change body of overridden methods use File | Settings | File Templates.
  }

  private class ItemConfigurable extends NamedConfigurable {
        private final T myItem;
        private final UnnamedConfigurable myConfigurable;

        public ItemConfigurable(T item) {
            super(myNamer.canRename(item), TREE_UPDATER);
            myItem = item;
            myConfigurable = createConfigurable(item);
        }

        @Override
        public void setDisplayName(String name) {
          NamedItemsListEditor.this.setDisplayName(myItem, name);
        }

        @Override
        public Object getEditableObject() {
            return myItem;
        }

        @Override
        public String getBannerSlogan() {
            return myNamer.getName(myItem);
        }

        @Override
        public JComponent createOptionsPanel() {
            return myConfigurable.createComponent();
        }

        @Override
        public String getDisplayName() {
            return myNamer.getName(myItem);
        }

        @Override
        public Icon getIcon(boolean expanded) {
            if (myShowIcons && myConfigurable instanceof Iconable) {
              return ((Iconable)myConfigurable).getIcon(0);
            }
            return null;
        }

    @Override
    public String getHelpTopic() {
            return null;
        }

        @Override
        public boolean isModified() {
            return myConfigurable.isModified();
        }

        @Override
        public void apply() throws ConfigurationException {
            myConfigurable.apply();
        }

        @Override
        public void reset() {
            myConfigurable.reset();
        }

        @Override
        public void disposeUIResources() {
            myConfigurable.disposeUIResources();
        }
    }

    @Override
    public boolean isModified() {
        if (myResultItems.size() != myItems.size()) return true;

        for (int i = 0; i < myItems.size(); i++) {
            if (!myComparer.equals(myItems.get(i), myResultItems.get(i))) return true;
        }

        return super.isModified();
    }

    @Override
    public void apply() throws ConfigurationException {
        super.apply();
        myResultItems = myItems;
    }

    protected List<T> getCurrentItems() {
      return Collections.unmodifiableList(myItems);
    }

    public List<T> getItems() {
        return myResultItems;
    }

    public T getSelectedItem() {
      //noinspection unchecked
      return (T) getSelectedObject();
    }


    private class CopyAction extends DumbAwareAction {
        public CopyAction() {
            super("Copy", "Copy", MasterDetailsComponent.COPY_ICON);
            registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_MASK)), myTree);
        }

        @Override
        public void actionPerformed(AnActionEvent event) {
            final String profileName = askForProfileName("Copy {0}");
            if (profileName == null) return;

            @SuppressWarnings("unchecked") final T clone = myCloner.copyOf((T) getSelectedObject());
            myNamer.setName(clone, profileName);
            addNewNode(clone);
            selectNodeInTree(clone);
            onItemCloned(clone);
        }


        @Override
        public void update(AnActionEvent event) {
            super.update(event);
            event.getPresentation().setEnabled(getSelectedObject() != null);
        }
    }

    protected void onItemCloned(T clone) {
    }

  private class AddAction extends DumbAwareAction {
        public AddAction() {
            super("Add", "Add", IconUtil.getAddIcon());
            registerCustomShortcutSet(CommonShortcuts.INSERT, myTree);
        }

        @Override
        public void actionPerformed(AnActionEvent event) {
          final T newItem = createItem();
          if (newItem != null) {
            onItemCreated(newItem);
          }
        }
    }

    public void selectItem(T item) {
        selectNodeInTree(findByName(myNamer.getName(item)));
    }

    @Nullable
    protected T createItem() {
      final String name = askForProfileName("Create new {0}");
      if (name == null) return null;
      final T newItem = myFactory.create();
      myNamer.setName(newItem, name);
      return newItem;
    }

    protected void onItemCreated(T newItem) {
      addNewNode(newItem);
      selectNodeInTree(newItem);
    }

}
