/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.jface.action.IAction;
import org.eclipse.ui.IKeyBindingService;
import org.eclipse.ui.INestableKeyBindingService;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchSite;
import org.eclipse.ui.commands.ActionHandler;
import org.eclipse.ui.commands.HandlerSubmission;
import org.eclipse.ui.commands.IHandler;
import org.eclipse.ui.commands.Priority;
import org.eclipse.ui.contexts.EnabledSubmission;

/**
 * This service provides a nestable implementation of a key binding service.
 * This class is provided for backwards compatibility only, and might be removed
 * in the future. All of the functionality is the class can be duplicated by
 * using the commands and contexts API.
 * 
 * @since 2.0
 */
public final class KeyBindingService implements INestableKeyBindingService {

    /**
     * The currently active nested service, if any. If there are no nested
     * services or none of them are active, then this value is <code>null</code>.
     */
    private IKeyBindingService activeService = null;

    /**
     * Whether this key binding service has been disposed.  A disposed key
     * binding service should not be used again.
     */
    private boolean disposed;

    /**
     * The set of context identifiers enabled in this key binding service (not
     * counting any nested services). This set may be empty, but it is never
     * <code>null</code>.
     */
    private Set enabledContextIds = Collections.EMPTY_SET;

    /**
     * The list of context submissions indicating the enabled state of the
     * context. This does not include those from nested services. This list may
     * be empty, but it is never <code>null</code>.
     */
    private List enabledSubmissions = new ArrayList();

    /**
     * The map of handler submissions, sorted by command identifiers. This does
     * not include those from nested services. This map may be empty, but it is
     * never <code>null</code>.
     */
    private Map handlerSubmissionsByCommandId = new HashMap();

    /**
     * The context submissions from the currently active nested service. This
     * value is <code>null</code> if there is no currently active nested
     * service.
     */
    private List nestedEnabledSubmissions = null;

    /**
     * The handler submissions from the currently active nested service. This
     * value is <code>null</code> if there is no currently active handler
     * service.
     */
    private List nestedHandlerSubmissions = null;

    /**
     * The map of workbench part sites to nested key binding services. This map
     * may be empty, but is never <code>null</code>.
     */
    private final Map nestedServices = new HashMap();

    /**
     * The parent for this key binding service; <code>null</code> if there is
     * no parent. If there is a parent, then this means that it should not do a
     * "live" update of its contexts or handlers, but should make a call to the
     * parent instead.
     */
    private final KeyBindingService parent;

    /**
     * The site within the workbench at which this service is provided. This
     * value should not be <code>null</code>.
     */
    private IWorkbenchPartSite workbenchPartSite;

    /**
     * Constructs a new instance of <code>KeyBindingService</code> on a given
     * workbench site. This instance is not nested.
     * 
     * @param workbenchPartSite
     *            The site for which this service will be responsible; should
     *            not be <code>null</code>.
     */
    public KeyBindingService(IWorkbenchPartSite workbenchPartSite) {
        this(workbenchPartSite, null);
    }

    /**
     * Constructs a new instance of <code>KeyBindingService</code> on a given
     * workbench site.
     * 
     * @param workbenchPartSite
     *            The site for which this service will be responsible; should
     *            not be <code>null</code>.
     * @param parent
     *            The parent key binding service, if any; <code>null</code> if
     *            none.
     */
    KeyBindingService(IWorkbenchPartSite workbenchPartSite,
            KeyBindingService parent) {
        this.workbenchPartSite = workbenchPartSite;
        this.parent = parent;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.INestableKeyBindingService#activateKeyBindingService(org.eclipse.ui.IWorkbenchSite)
     */
    public boolean activateKeyBindingService(IWorkbenchSite nestedSite) {
        if (disposed) {
			return false;
		}

        // Check if we should do a deactivation.
        if (nestedSite == null) {
            // We should do a deactivation, if there is one active.
            if (activeService == null) {
                // There is no active service. Do no work.
                return false;
            } else {
                // Deactivate the currently active nested service.
                deactivateNestedService();
                return true;
            }
        }

        // Attempt to activate a service.
        final IKeyBindingService service = (IKeyBindingService) nestedServices
                .get(nestedSite);
        if (service == null) {
            return false;
        }

        if (service == activeService) {
            // The service is already active.
            return false;
        }

        deactivateNestedService();
        activateNestedService(service);
        return true;
    }

    /**
     * Activates the given service without worrying about the currently active
     * service. This goes through the work of adding all of the nested context
     * ids as enabled submissions.
     * 
     * @param service
     *            The service to become active; if <code>null</code>, then
     *            the reference to the active service is set to
     *            <code>null</code> but nothing else happens.
     */
    private final void activateNestedService(final IKeyBindingService service) {
        if (disposed) {
			return;
		}

        /*
         * If I have a parent, and I'm the active service, then deactivate so
         * that I can make changes.
         */
        boolean active = false;
        boolean haveParent = (parent != null);
        if (haveParent) {
            active = (parent.activeService == this);
            if (active) {
                parent.deactivateNestedService();
            }
        }

        // Update the active service.
        activeService = service;

        // Check to see that the service isn't null.
        if (service == null) {
            return;
        }

        if (haveParent) {
            if (active) {
                parent.activateNestedService(this);
            }

        } else if (activeService instanceof KeyBindingService) {
            // I have no parent, so I can make the changes myself.
            final KeyBindingService nestedService = (KeyBindingService) activeService;

            // Update the contexts.
            nestedEnabledSubmissions = nestedService.getEnabledSubmissions();
            normalizeSites(nestedEnabledSubmissions);
            Workbench.getInstance().getContextSupport().addEnabledSubmissions(
                    nestedEnabledSubmissions);

            // Update the handlers.
            nestedHandlerSubmissions = nestedService.getHandlerSubmissions();
            normalizeSites(nestedHandlerSubmissions);
            Workbench.getInstance().getCommandSupport().addHandlerSubmissions(
                    nestedHandlerSubmissions);
        }
    }

    /**
     * Deactives the currently active service. This nulls out the reference, and
     * removes all the enabled submissions for the nested service.
     */
    private final void deactivateNestedService() {
        if (disposed) {
			return;
		}

        // Don't do anything if there is no active service.
        if (activeService == null) {
            return;
        }

        // Check to see if there is a parent.
        boolean active = false;
        if (parent != null) {
            // Check if I'm the active service.
            if (parent.activeService == this) {
                active = true;
                // Deactivate myself so I can make changes.
                parent.deactivateNestedService();
            }

        } else if (activeService instanceof KeyBindingService) {
            // Remove all the nested context ids.
            Workbench.getInstance().getContextSupport()
                    .removeEnabledSubmissions(nestedEnabledSubmissions);

            /*
             * Remove all of the nested handler submissions. The handlers here
             * weren't created by this instance (but by the nest instance), and
             * hence can't be disposed here.
             */
            Workbench.getInstance().getCommandSupport()
                    .removeHandlerSubmissions(nestedHandlerSubmissions);

        }

        // Clear our reference to the active service.
        activeService = null;

        // If necessary, let my parent know that changes have occurred.
        if (active) {
            parent.activateNestedService(this);
        }
    }

    /**
     * Disposes this key binding service. This clears out all of the submissions
     * held by this service, and its nested services.
     */
    public void dispose() {
        if (!disposed) {
            deactivateNestedService();
            disposed = true;

            Workbench
                    .getInstance()
                    .getContextSupport()
                    .removeEnabledSubmissions(new ArrayList(enabledSubmissions));
            enabledSubmissions.clear();

            /*
             * Each removed handler submission, must dispose its corresponding
             * handler -- as these handlers only exist inside of this class.
             */
            final List submissions = new ArrayList(
                    handlerSubmissionsByCommandId.values());
            final Iterator submissionItr = submissions.iterator();
            while (submissionItr.hasNext()) {
                ((HandlerSubmission) submissionItr.next()).getHandler()
                        .dispose();
            }
            Workbench.getInstance().getCommandSupport()
                    .removeHandlerSubmissions(submissions);
            handlerSubmissionsByCommandId.clear();

            for (Iterator iterator = nestedServices.values().iterator(); iterator
                    .hasNext();) {
                KeyBindingService keyBindingService = (KeyBindingService) iterator
                        .next();
                keyBindingService.dispose();
            }

            nestedEnabledSubmissions = null;
            nestedHandlerSubmissions = null;
            nestedServices.clear();
        }
    }

    /**
     * Gets a copy of all the enabled submissions in the nesting chain.
     * 
     * @return All of the nested enabled submissions -- including the ones from
     *         this service. This list may be empty, but is never
     *         <code>null</code>.
     */
    private final List getEnabledSubmissions() {
        if (disposed) {
			return null;
		}

        final List submissions = new ArrayList(enabledSubmissions);
        if (activeService instanceof KeyBindingService) {
            final KeyBindingService nestedService = (KeyBindingService) activeService;
            submissions.addAll(nestedService.getEnabledSubmissions());
        }
        return submissions;
    }

    /**
     * Gets a copy of all the handler submissions in the nesting chain.
     * 
     * @return All of the nested handler submissions -- including the ones from
     *         this service. This list may be empty, but is never
     *         <code>null</code>.
     */
    private final List getHandlerSubmissions() {
        if (disposed) {
			return null;
		}

        final List submissions = new ArrayList(handlerSubmissionsByCommandId
                .values());
        if (activeService instanceof KeyBindingService) {
            final KeyBindingService nestedService = (KeyBindingService) activeService;
            submissions.addAll(nestedService.getHandlerSubmissions());
        }
        return submissions;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.INestableKeyBindingService#getKeyBindingService(org.eclipse.ui.IWorkbenchSite)
     */
    public IKeyBindingService getKeyBindingService(IWorkbenchSite nestedSite) {
        if (disposed) {
			return null;
		}

        if (nestedSite == null) {
            return null;
        }

        IKeyBindingService service = (IKeyBindingService) nestedServices
                .get(nestedSite);
        if (service == null) {
            // TODO the INestedKeyBindingService API should be based on
            // IWorkbenchPartSite..
            if (nestedSite instanceof IWorkbenchPartSite) {
				service = new KeyBindingService(
                        (IWorkbenchPartSite) nestedSite, this);
			} else {
				service = new KeyBindingService(null, this);
			}

            nestedServices.put(nestedSite, service);
        }

        return service;
    }

    public String[] getScopes() {
        if (disposed) {
			return null;
		}

        // Get the nested scopes, if any.
        final String[] nestedScopes;
        if (activeService == null) {
            nestedScopes = null;
        } else {
            nestedScopes = activeService.getScopes();
        }

        // Build the list of active scopes
        final Set activeScopes = new HashSet();
        activeScopes.addAll(enabledContextIds);
        if (nestedScopes != null) {
            for (int i = 0; i < nestedScopes.length; i++) {
                activeScopes.add(nestedScopes[i]);
            }
        }

        return (String[]) activeScopes.toArray(new String[activeScopes.size()]);
    }

    /**
     * Replaces the active workbench site with this service's active workbench
     * site. This ensures that the context manager will recognize the context as
     * active. Note: this method modifies the list in place; it is
     * <em>destructive</em>.
     * 
     * @param submissionsToModify
     *            The submissions list to modify; must not be <code>null</code>,
     *            but may be empty.
     */
    private final void normalizeSites(final List submissionsToModify) {
        if (disposed) {
			return;
		}

        final int size = submissionsToModify.size();
        for (int i = 0; i < size; i++) {
            final Object submission = submissionsToModify.get(i);
            final Object replacementSubmission;

            if (submission instanceof EnabledSubmission) {
                final EnabledSubmission enabledSubmission = (EnabledSubmission) submission;
                if (!workbenchPartSite.equals(enabledSubmission
                        .getActiveWorkbenchPartSite())) {
                    replacementSubmission = new EnabledSubmission(null,
                            enabledSubmission.getActiveShell(),
                            workbenchPartSite, enabledSubmission.getContextId());
                } else {
                    replacementSubmission = enabledSubmission;
                }

            } else if (submission instanceof HandlerSubmission) {
                final HandlerSubmission handlerSubmission = (HandlerSubmission) submission;
                if (!workbenchPartSite.equals(handlerSubmission
                        .getActiveWorkbenchPartSite())) {
                    replacementSubmission = new HandlerSubmission(null,
                            handlerSubmission.getActiveShell(),
                            workbenchPartSite,
                            handlerSubmission.getCommandId(), handlerSubmission
                                    .getHandler(), handlerSubmission
                                    .getPriority());
                } else {
                    replacementSubmission = handlerSubmission;
                }

            } else {
                replacementSubmission = submission;
            }

            submissionsToModify.set(i, replacementSubmission);
        }

    }

    public void registerAction(IAction action) {
        if (disposed) {
			return;
		}

        unregisterAction(action);
        String commandId = action.getActionDefinitionId();
        if (commandId != null) {
            /*
             * If I have a parent and I'm active, de-activate myself while
             * making changes.
             */
            boolean active = false;
            if ((parent != null) && (parent.activeService == this)) {
                active = true;
                parent.deactivateNestedService();
            }

            // Create the new submission
            IHandler handler = new ActionHandler(action);
            HandlerSubmission handlerSubmission = new HandlerSubmission(null,
                    workbenchPartSite.getShell(), workbenchPartSite, commandId,
                    handler, Priority.MEDIUM);
            handlerSubmissionsByCommandId.put(commandId, handlerSubmission);

            // Either submit the new handler myself, or simply re-activate.
            if (parent != null) {
                if (active) {
                    parent.activateNestedService(this);
                }
            } else {
                Workbench.getInstance().getCommandSupport()
                        .addHandlerSubmission(handlerSubmission);
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.INestableKeyBindingService#removeKeyBindingService(org.eclipse.ui.IWorkbenchSite)
     */
    public boolean removeKeyBindingService(IWorkbenchSite nestedSite) {
        if (disposed) {
			return false;
		}

        final IKeyBindingService service = (IKeyBindingService) nestedServices
                .remove(nestedSite);
        if (service == null) {
            return false;
        }

        if (service.equals(activeService)) {
            deactivateNestedService();
        }

        return true;
    }

    public void setScopes(String[] scopes) {
        if (disposed) {
			return;
		}

        // Either deactivate myself, or remove the previous submissions myself.
        boolean active = false;
        if ((parent != null) && (parent.activeService == this)) {
            active = true;
            parent.deactivateNestedService();
        } else {
            Workbench.getInstance().getContextSupport()
                    .removeEnabledSubmissions(enabledSubmissions);
        }
        enabledSubmissions.clear();

        // Determine the new list of submissions.
        enabledContextIds = new HashSet(Arrays.asList(scopes));
        for (Iterator iterator = enabledContextIds.iterator(); iterator
                .hasNext();) {
            String contextId = (String) iterator.next();
            enabledSubmissions.add(new EnabledSubmission(null, null,
                    workbenchPartSite, contextId));
        }

        // Submit the new contexts myself, or simply re-active myself.
        if (parent != null) {
            if (active) {
                parent.activateNestedService(this);
            }
        } else {
            Workbench.getInstance().getContextSupport().addEnabledSubmissions(
                    enabledSubmissions);
        }
    }

    public void unregisterAction(IAction action) {
        if (disposed) {
			return;
		}

        String commandId = action.getActionDefinitionId();

        if (commandId != null) {
            // Deactivate this service while making changes.
            boolean active = false;
            if ((parent != null) && (parent.activeService == this)) {
                active = true;
                parent.deactivateNestedService();
            }

            // Remove the current submission, if any.
            HandlerSubmission handlerSubmission = (HandlerSubmission) handlerSubmissionsByCommandId
                    .remove(commandId);

            /*
             * Either activate this service again, or remove the submission
             * myself.
             */
            if (parent != null) {
                if (active) {
                    parent.activateNestedService(this);
                }
            } else {
            	if (handlerSubmission != null) {
                    Workbench.getInstance().getCommandSupport()
                            .removeHandlerSubmission(handlerSubmission);
                    handlerSubmission.getHandler().dispose();
                }
            }
        }
    }
}
