/*
 * The contents of this file are subject to the terms of the Common Development
 * and Distribution License (the License). You may not use this file except in
 * compliance with the License.
 *
 * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
 * or http://www.netbeans.org/cddl.txt.
 * 
 * When distributing Covered Code, include this CDDL Header Notice in each file
 * and include the License file at http://www.netbeans.org/cddl.txt.
 * If applicable, add the following below the CDDL Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.autoupdate.catalog;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Set;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import org.netbeans.Module;
import org.netbeans.core.IDESettings;
import org.openide.awt.Mnemonics;
import org.openide.nodes.Node;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.SharedClassObject;
import org.openide.util.actions.NodeAction;
import org.openide.util.actions.Presenter.Popup;

/**
 *
 * @author Jiri Rechtacek
 */
public class ModuleNodeActions {
    
    /** Creates a new instance of ModuleNodeActions */
    public ModuleNodeActions () {
    }
    
    private static ModuleDeleter deleter;
    
    public static class EnableDisableAction extends NodeAction {
        private String name;

        protected void performAction (final Node[] activatedNodes) {
            assert activatedNodes != null : "Cannot performAction when activatedNodes is null";
            final Boolean b = ModuleNodeUtils.isEnableCandidate (activatedNodes);
            assert b != null : "Cannot performAction if mixed statuses on activatedNodes " + Arrays.asList (activatedNodes);
            
            // fix of 62480: join all enable/disable to one group
            ModuleBean.AllModulesBean.getDefault ().pause ();
            Set/*<ModuleBean>*/ beans = ModuleNodeUtils.getAllSelectedModuleBeans (activatedNodes);
            Iterator/*<ModuleBean>*/ it = beans.iterator ();
            while (it.hasNext ()) {
                ModuleBean bean = (ModuleBean) it.next ();
                bean.setEnabled (b.booleanValue ());
            }
            ModuleBean.AllModulesBean.getDefault ().resume ();
        }

        protected boolean enable (Node[] activatedNodes) {
            if (activatedNodes == null) {
                return false;
            }
            
            Set/*<ModuleNode.Item>*/ items = ModuleNodeUtils.getAllSelectedModuleItems (activatedNodes);

            boolean allowed = ! items.isEmpty ();
            Iterator it = items.iterator ();
            String moduleName = ""; // NOI18N
            while (allowed && it.hasNext ()) {
                Object o = it.next ();
                assert o instanceof ModuleNode.Item : "Object " + o + " is instanceof ModuleNode.Item";
                Module m = ((ModuleNode.Item) o).getItem ().getModule ();
                moduleName = m.getDisplayName ();
                allowed = allowed && ModuleNodeUtils.isEnableAllowed (m);
            }
            
            // set action's name
            Boolean b = ModuleNodeUtils.isEnableCandidate (activatedNodes);

            // special handling of category
            if (activatedNodes.length == 1 && ! (activatedNodes [0] instanceof ModuleNode.Item)) {
                name = NbBundle.getMessage (ModuleNodeActions.class, "CTL_ModuleNodeActions_EnableDisableAction_format", // NOI18N
                            b == null || b.booleanValue () ? NbBundle.getMessage (ModuleNodeActions.class, "CTL_ModuleNodeActions_EnableDisableAction_enable") : // NOI18N
                                                             NbBundle.getMessage (ModuleNodeActions.class, "CTL_ModuleNodeActions_EnableDisableAction_disable"), // NOI18N
                            activatedNodes[0].getDisplayName ()); // NOI18N
            } else {
                name = NbBundle.getMessage (ModuleNodeActions.class, "CTL_ModuleNodeActions_EnableDisableAction_format", // NOI18N
                            b == null || b.booleanValue () ? NbBundle.getMessage (ModuleNodeActions.class, "CTL_ModuleNodeActions_EnableDisableAction_enable") : // NOI18N
                                                             NbBundle.getMessage (ModuleNodeActions.class, "CTL_ModuleNodeActions_EnableDisableAction_disable"), // NOI18N
                            items.size () > 1 ? NbBundle.getMessage (ModuleNodeActions.class, "CTL_ModuleNodeActions_EnableDisableAction_many") : moduleName); // NOI18N
            }
            
            return allowed && (ModuleNodeUtils.isEnableCandidate (activatedNodes) != null);
        }

        public String getName() {
            return name;
        }

        public HelpCtx getHelpCtx() {
            //return new HelpCtx (ModuleNodeActions.EnableAllAction.class);
            return null;
        }

        protected boolean asynchronous() {
            return true;
        }
    }

    public static class EnableAllAction extends NodeAction {

        protected void performAction (Node[] activatedNodes) {
            assert activatedNodes != null : "Cannot performAction when activatedNodes is null";
            
            // fix of 62480: join all enable/disable to one group
            ModuleBean.AllModulesBean.getDefault ().pause ();
            ModuleBean [] beans = ModuleBean.AllModulesBean.getDefault ().getModules ();
            for (int i = 0; i < beans.length; i++) {
                if (! beans [i].isEnabled () && ModuleNodeUtils.isEnableAllowed (beans [i].getModule ())) {
                    beans [i].setEnabled (true);
                }
            }
            ModuleBean.AllModulesBean.getDefault ().resume ();
        }

        protected boolean enable (Node[] activatedNodes) {
            // XXX: don't enable if all modules are enabled
            return activatedNodes != null && activatedNodes.length > 0;
        }

        public String getName() {
            return NbBundle.getMessage (ModuleNodeActions.class, "CTL_ModuleNodeActions_EnableAllAction"); // NOI18N
        }

        public HelpCtx getHelpCtx() {
            //return new HelpCtx (ModuleNodeActions.EnableDisableAction.class);
            return null;
        }

        protected boolean asynchronous() {
            return true;
        }
    }

    public static class UninstallAction extends NodeAction {
        private String name;
        
        protected void performAction (Node[] activatedNodes) {
            ModuleNodeUtils.doUninstall (activatedNodes);
        }

        protected boolean enable (Node[] activatedNodes) {
            name = ModuleNodeUtils.getUninstallActionName (activatedNodes, name);
            return ModuleNodeUtils.canUninstall (activatedNodes);
        }

        public String getName() {
            return name;
        }

        public HelpCtx getHelpCtx() {
            //return new HelpCtx (ModuleNodeActions.UninstallAction.class);
            return null;
        }

        protected boolean asynchronous() {
            return true;
        }
    }

    public static class SortAction extends NodeAction implements Popup {
        
        // private fields
        JMenu subMenu;
        JCheckBoxMenuItem sortByCategory;
        JCheckBoxMenuItem sortByName;
        
        static final private IDESettings settings = (IDESettings) SharedClassObject.findObject (IDESettings.class, true);
        
        protected void performAction (Node[] activatedNodes) {
        }

        protected boolean enable (Node[] activatedNodes) {
            return true;
        }

        public String getName () {
            return NbBundle.getMessage (ModuleNodeActions.class, "CTL_ModuleNodeActions_SortAction"); // NOI18N
        }

        public HelpCtx getHelpCtx () {
            return null;
        }
        
        public JMenuItem getPopupPresenter() {
            return getSubmenuPopupPresenter();
        }
        
        public JMenuItem getSubmenuPopupPresenter() {
            if (subMenu == null) {
                
                subMenu = new JMenu ();
                Mnemonics.setLocalizedText (subMenu, NbBundle.getMessage (ModuleNodeActions.class, "CTL_ModuleNodeActions_SortAction")); // NOI18N
                
                sortByCategory = new JCheckBoxMenuItem ();
                Mnemonics.setLocalizedText (sortByCategory, NbBundle.getMessage (ModuleNodeActions.class, "CTL_ModuleNodeActions_SortByCategory")); // NOI18N
                sortByCategory.addActionListener (new MenuListener ());
                subMenu.add (sortByCategory);
                
                sortByName = new JCheckBoxMenuItem ();
                Mnemonics.setLocalizedText (sortByName, NbBundle.getMessage (ModuleNodeActions.class, "CTL_ModuleNodeActions_SortByName")); // NOI18N
                sortByName.addActionListener (new MenuListener ());
                subMenu.add (sortByName);
                
            }
            sortByCategory.setState (IDESettings.MODULES_SORT_CATEGORY == settings.getModulesSortMode ());
            sortByName.setState (IDESettings.MODULES_SORT_DISPLAYNAME == settings.getModulesSortMode ());
            return subMenu;
        }
        
        private class MenuListener implements ActionListener {

            public void actionPerformed (ActionEvent e) {
                JMenuItem source = (JMenuItem)e.getSource ();
                
                if (sortByCategory.equals (source)) {
                    settings.setModulesSortMode (IDESettings.MODULES_SORT_CATEGORY);
                } else if (sortByName.equals (source)) {
                    settings.setModulesSortMode (IDESettings.MODULES_SORT_DISPLAYNAME);
                } else {
                    assert false : "Invalid source " + source + " in actionPerformed()";
                }

            }

        }


    }
}
