/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
 *
 * 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.android.ide.eclipse.adt.internal.editors.layout.gle2;

import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ATTR_ID;
import static com.android.SdkConstants.EXPANDABLE_LIST_VIEW;
import static com.android.SdkConstants.FQCN_GESTURE_OVERLAY_VIEW;
import static com.android.SdkConstants.FQCN_IMAGE_VIEW;
import static com.android.SdkConstants.FQCN_LINEAR_LAYOUT;
import static com.android.SdkConstants.FQCN_TEXT_VIEW;
import static com.android.SdkConstants.GRID_VIEW;
import static com.android.SdkConstants.LIST_VIEW;
import static com.android.SdkConstants.SPINNER;
import static com.android.SdkConstants.VIEW_FRAGMENT;

import com.android.SdkConstants;
import com.android.ide.common.api.INode;
import com.android.ide.common.api.IViewRule;
import com.android.ide.common.api.RuleAction;
import com.android.ide.common.api.RuleAction.Choices;
import com.android.ide.common.api.RuleAction.NestedAction;
import com.android.ide.common.api.RuleAction.Toggle;
import com.android.ide.common.layout.BaseViewRule;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeFactory;
import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy;
import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.ChangeLayoutAction;
import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.ChangeViewAction;
import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.ExtractIncludeAction;
import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.ExtractStyleAction;
import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.UnwrapAction;
import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.UseCompoundDrawableAction;
import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.WrapInAction;
import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;

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

/**
 * Helper class that is responsible for adding and managing the dynamic menu items
 * contributed by the {@link IViewRule} instances, based on the current selection
 * on the {@link LayoutCanvas}.
 * <p/>
 * This class is tied to a specific {@link LayoutCanvas} instance and a root {@link MenuManager}.
 * <p/>
 * Two instances of this are used: one created by {@link LayoutCanvas} and the other one
 * created by {@link OutlinePage}. Different root {@link MenuManager}s are populated, however
 * they are both linked to the current selection state of the {@link LayoutCanvas}.
 */
class DynamicContextMenu {
    public static String DEFAULT_ACTION_SHORTCUT = "F2"; //$NON-NLS-1$
    public static int DEFAULT_ACTION_KEY = SWT.F2;

    /** The XML layout editor that contains the canvas that uses this menu. */
    private final LayoutEditorDelegate mEditorDelegate;

    /** The layout canvas that displays this context menu. */
    private final LayoutCanvas mCanvas;

    /** The root menu manager of the context menu. */
    private final MenuManager mMenuManager;

    /**
     * Creates a new helper responsible for adding and managing the dynamic menu items
     * contributed by the {@link IViewRule} instances, based on the current selection
     * on the {@link LayoutCanvas}.
     * @param editorDelegate the editor owning the menu
     * @param canvas The {@link LayoutCanvas} providing the selection, the node factory and
     *   the rules engine.
     * @param rootMenu The root of the context menu displayed. In practice this may be the
     *   context menu manager of the {@link LayoutCanvas} or the one from {@link OutlinePage}.
     */
    public DynamicContextMenu(
            LayoutEditorDelegate editorDelegate,
            LayoutCanvas canvas,
            MenuManager rootMenu) {
        mEditorDelegate = editorDelegate;
        mCanvas = canvas;
        mMenuManager = rootMenu;

        setupDynamicMenuActions();
    }

    /**
     * Setups the menu manager to receive dynamic menu contributions from the {@link IViewRule}s
     * when it's about to be shown.
     */
    private void setupDynamicMenuActions() {
        // Remember how many static actions we have. Then each time the menu is
        // shown, find dynamic contributions based on the current selection and insert
        // them at the beginning of the menu.
        final int numStaticActions = mMenuManager.getSize();
        mMenuManager.addMenuListener(new IMenuListener() {
            @Override
            public void menuAboutToShow(IMenuManager manager) {

                // Remove any previous dynamic contributions to keep only the
                // default static items.
                int n = mMenuManager.getSize() - numStaticActions;
                if (n > 0) {
                    IContributionItem[] items = mMenuManager.getItems();
                    for (int i = 0; i < n; i++) {
                        mMenuManager.remove(items[i]);
                    }
                }

                // Now add all the dynamic menu actions depending on the current selection.
                populateDynamicContextMenu();
            }
        });

    }

    /**
     * This method is invoked by <code>menuAboutToShow</code> on {@link #mMenuManager}.
     * All previous dynamic menu actions have been removed and this method can now insert
     * any new actions that depend on the current selection.
     */
    private void populateDynamicContextMenu() {
        //  Create the actual menu contributions
        String endId = mMenuManager.getItems()[0].getId();

        Separator sep = new Separator();
        sep.setId("-dyn-gle-sep");  //$NON-NLS-1$
        mMenuManager.insertBefore(endId, sep);
        endId = sep.getId();

        List<SelectionItem> selections = mCanvas.getSelectionManager().getSelections();
        if (selections.size() == 0) {
            return;
        }
        List<INode> nodes = new ArrayList<INode>(selections.size());
        for (SelectionItem item : selections) {
            nodes.add(item.getNode());
        }

        List<IContributionItem> menuItems = getMenuItems(nodes);
        for (IContributionItem menuItem : menuItems) {
            mMenuManager.insertBefore(endId, menuItem);
        }

        insertTagSpecificMenus(endId);
        insertVisualRefactorings(endId);
        insertParentItems(endId);
    }

    /**
     * Returns the list of node-specific actions applicable to the given
     * collection of nodes
     *
     * @param nodes the collection of nodes to look up actions for
     * @return a list of contribution items applicable for all the nodes
     */
    private List<IContributionItem> getMenuItems(List<INode> nodes) {
        Map<INode, List<RuleAction>> allActions = new HashMap<INode, List<RuleAction>>();
        for (INode node : nodes) {
            List<RuleAction> actionList = getMenuActions((NodeProxy) node);
            allActions.put(node, actionList);
        }

        Set<String> availableIds = computeApplicableActionIds(allActions);

        // +10: Make room for separators too
        List<IContributionItem> items = new ArrayList<IContributionItem>(availableIds.size() + 10);

        // We'll use the actions returned by the first node. Even when there
        // are multiple items selected, we'll use the first action, but pass
        // the set of all selected nodes to that first action. Actions are required
        // to work this way to facilitate multi selection and actions which apply
        // to multiple nodes.
        NodeProxy first = (NodeProxy) nodes.get(0);
        List<RuleAction> firstSelectedActions = allActions.get(first);
        String defaultId = getDefaultActionId(first);
        for (RuleAction action : firstSelectedActions) {
            if (!availableIds.contains(action.getId())
                    && !(action instanceof RuleAction.Separator)) {
                // This action isn't supported by all selected items.
                continue;
            }

            items.add(createContributionItem(action, nodes, defaultId));
        }

        return items;
    }

    private void insertParentItems(String endId) {
        List<SelectionItem> selection = mCanvas.getSelectionManager().getSelections();
        if (selection.size() == 1) {
            mMenuManager.insertBefore(endId, new Separator());
            INode parent = selection.get(0).getNode().getParent();
            while (parent != null) {
                String id = parent.getStringAttr(ANDROID_URI, ATTR_ID);
                String label;
                if (id != null && id.length() > 0) {
                    label = BaseViewRule.stripIdPrefix(id);
                } else {
                    // Use the view name, such as "Button", as the label
                    label = parent.getFqcn();
                    // Strip off package
                    label = label.substring(label.lastIndexOf('.') + 1);
                }
                mMenuManager.insertBefore(endId, new NestedParentMenu(label, parent));
                parent = parent.getParent();
            }
            mMenuManager.insertBefore(endId, new Separator());
        }
    }

    private void insertVisualRefactorings(String endId) {
        // Extract As <include> refactoring, Wrap In Refactoring, etc.
        List<SelectionItem> selection = mCanvas.getSelectionManager().getSelections();
        if (selection.size() == 0) {
            return;
        }
        // Only include the menu item if you are not right clicking on a root,
        // or on an included view, or on a non-contiguous selection
        mMenuManager.insertBefore(endId, new Separator());
        if (selection.size() == 1 && selection.get(0).getViewInfo() != null
                && selection.get(0).getViewInfo().getName().equals(FQCN_LINEAR_LAYOUT)) {
            CanvasViewInfo info = selection.get(0).getViewInfo();
            List<CanvasViewInfo> children = info.getChildren();
            if (children.size() == 2) {
                String first = children.get(0).getName();
                String second = children.get(1).getName();
                if ((first.equals(FQCN_IMAGE_VIEW) && second.equals(FQCN_TEXT_VIEW))
                        || (first.equals(FQCN_TEXT_VIEW) && second.equals(FQCN_IMAGE_VIEW))) {
                    mMenuManager.insertBefore(endId, UseCompoundDrawableAction.create(
                            mEditorDelegate));
                }
            }
        }
        mMenuManager.insertBefore(endId, ExtractIncludeAction.create(mEditorDelegate));
        mMenuManager.insertBefore(endId, ExtractStyleAction.create(mEditorDelegate));
        mMenuManager.insertBefore(endId, WrapInAction.create(mEditorDelegate));
        if (selection.size() == 1 && !(selection.get(0).isRoot())) {
            mMenuManager.insertBefore(endId, UnwrapAction.create(mEditorDelegate));
        }
        if (selection.size() == 1 && (selection.get(0).isLayout() ||
                selection.get(0).getViewInfo().getName().equals(FQCN_GESTURE_OVERLAY_VIEW))) {
            mMenuManager.insertBefore(endId, ChangeLayoutAction.create(mEditorDelegate));
        } else {
            mMenuManager.insertBefore(endId, ChangeViewAction.create(mEditorDelegate));
        }
        mMenuManager.insertBefore(endId, new Separator());
    }

    /** "Preview List Content" pull-right menu for lists, "Preview Fragment" for fragments, etc. */
    private void insertTagSpecificMenus(String endId) {

        List<SelectionItem> selection = mCanvas.getSelectionManager().getSelections();
        if (selection.size() == 0) {
            return;
        }
        for (SelectionItem item : selection) {
            UiViewElementNode node = item.getViewInfo().getUiViewNode();
            String name = node.getDescriptor().getXmlLocalName();
            boolean isGrid = name.equals(GRID_VIEW);
            boolean isSpinner = name.equals(SPINNER);
            if (name.equals(LIST_VIEW) || name.equals(EXPANDABLE_LIST_VIEW)
                    || isGrid || isSpinner) {
                mMenuManager.insertBefore(endId, new Separator());
                mMenuManager.insertBefore(endId, new ListViewTypeMenu(mCanvas, isGrid, isSpinner));
                return;
            } else if (name.equals(VIEW_FRAGMENT) && selection.size() == 1) {
                mMenuManager.insertBefore(endId, new Separator());
                mMenuManager.insertBefore(endId, new FragmentMenu(mCanvas));
                return;
            }
        }
    }

    /**
     * Given a map from selection items to list of applicable actions (produced
     * by {@link #computeApplicableActions()}) this method computes the set of
     * common actions and returns the action ids of these actions.
     *
     * @param actions a map from selection item to list of actions applicable to
     *            that selection item
     * @return set of action ids for the actions that are present in the action
     *         lists for all selected items
     */
    private Set<String> computeApplicableActionIds(Map<INode, List<RuleAction>> actions) {
        if (actions.size() > 1) {
            // More than one view is selected, so we have to filter down the available
            // actions such that only those actions that are defined for all the views
            // are shown
            Map<String, Integer> idCounts = new HashMap<String, Integer>();
            for (Map.Entry<INode, List<RuleAction>> entry : actions.entrySet()) {
                List<RuleAction> actionList = entry.getValue();
                for (RuleAction action : actionList) {
                    if (!action.supportsMultipleNodes()) {
                        continue;
                    }
                    String id = action.getId();
                    if (id != null) {
                        assert id != null : action;
                        Integer count = idCounts.get(id);
                        if (count == null) {
                            idCounts.put(id, Integer.valueOf(1));
                        } else {
                            idCounts.put(id, count + 1);
                        }
                    }
                }
            }
            Integer selectionCount = Integer.valueOf(actions.size());
            Set<String> validIds = new HashSet<String>(idCounts.size());
            for (Map.Entry<String, Integer> entry : idCounts.entrySet()) {
                Integer count = entry.getValue();
                if (selectionCount.equals(count)) {
                    String id = entry.getKey();
                    validIds.add(id);
                }
            }
            return validIds;
        } else {
            List<RuleAction> actionList = actions.values().iterator().next();
            Set<String> validIds = new HashSet<String>(actionList.size());
            for (RuleAction action : actionList) {
                String id = action.getId();
                validIds.add(id);
            }
            return validIds;
        }
    }

    /**
     * Returns the menu actions computed by the rule associated with this node.
     *
     * @param node the canvas node we need menu actions for
     * @return a list of {@link RuleAction} objects applicable to the node
     */
    private List<RuleAction> getMenuActions(NodeProxy node) {
        List<RuleAction> actions = mCanvas.getRulesEngine().callGetContextMenu(node);
        if (actions == null || actions.size() == 0) {
            return null;
        }

        return actions;
    }

    /**
     * Returns the default action id, or null
     *
     * @param node the node to look up the default action for
     * @return the action id, or null
     */
    private String getDefaultActionId(NodeProxy node) {
        return mCanvas.getRulesEngine().callGetDefaultActionId(node);
    }

    /**
     * Creates a {@link ContributionItem} for the given {@link RuleAction}.
     *
     * @param action the action to create a {@link ContributionItem} for
     * @param nodes the set of nodes the action should be applied to
     * @param defaultId if not non null, the id of an action which should be considered default
     * @return a new {@link ContributionItem} which implements the given action
     *         on the given nodes
     */
    private ContributionItem createContributionItem(final RuleAction action,
            final List<INode> nodes, final String defaultId) {
        if (action instanceof RuleAction.Separator) {
            return new Separator();
        } else if (action instanceof NestedAction) {
            NestedAction parentAction = (NestedAction) action;
            return new ActionContributionItem(new NestedActionMenu(parentAction, nodes));
        } else if (action instanceof Choices) {
            Choices parentAction = (Choices) action;
            return new ActionContributionItem(new NestedChoiceMenu(parentAction, nodes));
        } else if (action instanceof Toggle) {
            return new ActionContributionItem(createToggleAction(action, nodes));
        } else {
            return new ActionContributionItem(createPlainAction(action, nodes, defaultId));
        }
    }

    private Action createToggleAction(final RuleAction action, final List<INode> nodes) {
        Toggle toggleAction = (Toggle) action;
        final boolean isChecked = toggleAction.isChecked();
        Action a = new Action(action.getTitle(), IAction.AS_CHECK_BOX) {
            @Override
            public void run() {
                String label = createActionLabel(action, nodes);
                mEditorDelegate.getEditor().wrapUndoEditXmlModel(label, new Runnable() {
                    @Override
                    public void run() {
                        action.getCallback().action(action, nodes,
                                null/* no valueId for a toggle */, !isChecked);
                        applyPendingChanges();
                    }
                });
            }
        };
        a.setId(action.getId());
        a.setChecked(isChecked);
        return a;
    }

    private IAction createPlainAction(final RuleAction action, final List<INode> nodes,
            final String defaultId) {
        IAction a = new Action(action.getTitle(), IAction.AS_PUSH_BUTTON) {
            @Override
            public void run() {
                String label = createActionLabel(action, nodes);
                mEditorDelegate.getEditor().wrapUndoEditXmlModel(label, new Runnable() {
                    @Override
                    public void run() {
                        action.getCallback().action(action, nodes, null,
                                Boolean.TRUE);
                        applyPendingChanges();
                    }
                });
            }
        };

        String id = action.getId();
        if (defaultId != null && id.equals(defaultId)) {
            a.setAccelerator(DEFAULT_ACTION_KEY);
            String text = a.getText();
            text = text + '\t' + DEFAULT_ACTION_SHORTCUT;
            a.setText(text);

        } else if (ATTR_ID.equals(id)) {
            // Keep in sync with {@link LayoutCanvas#handleKeyPressed}
            if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN) {
                a.setAccelerator('R' | SWT.MOD1 | SWT.MOD3);
                // Option+Command
                a.setText(a.getText().trim() + "\t\u2325\u2318R"); //$NON-NLS-1$
            } else if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_LINUX) {
                a.setAccelerator('R' | SWT.MOD2 | SWT.MOD3);
                a.setText(a.getText() + "\tShift+Alt+R"); //$NON-NLS-1$
            } else {
                a.setAccelerator('R' | SWT.MOD2 | SWT.MOD3);
                a.setText(a.getText() + "\tAlt+Shift+R"); //$NON-NLS-1$
            }
        }
        a.setId(id);
        return a;
    }

    private static String createActionLabel(final RuleAction action, final List<INode> nodes) {
        String label = action.getTitle();
        if (nodes.size() > 1) {
            label += String.format(" (%d elements)", nodes.size());
        }
        return label;
    }

    /**
     * The {@link NestedParentMenu} provides submenu content which adds actions
     * available on one of the selected node's parent nodes. This will be
     * similar to the menu content for the selected node, except the parent
     * menus will not be embedded within the nested menu.
     */
    private class NestedParentMenu extends SubmenuAction {
        INode mParent;

        NestedParentMenu(String title, INode parent) {
            super(title);
            mParent = parent;
        }

        @Override
        protected void addMenuItems(Menu menu) {
            List<SelectionItem> selection = mCanvas.getSelectionManager().getSelections();
            if (selection.size() == 0) {
                return;
            }

            List<IContributionItem> menuItems = getMenuItems(Collections.singletonList(mParent));
            for (IContributionItem menuItem : menuItems) {
                menuItem.fill(menu, -1);
            }
        }
    }

    /**
     * The {@link NestedActionMenu} creates a lazily populated pull-right menu
     * where the children are {@link RuleAction}'s themselves.
     */
    private class NestedActionMenu extends SubmenuAction {
        private final NestedAction mParentAction;
        private final List<INode> mNodes;

        NestedActionMenu(NestedAction parentAction, List<INode> nodes) {
            super(parentAction.getTitle());
            mParentAction = parentAction;
            mNodes = nodes;

            assert mNodes.size() > 0;
        }

        @Override
        protected void addMenuItems(Menu menu) {
            Map<INode, List<RuleAction>> allActions = new HashMap<INode, List<RuleAction>>();
            for (INode node : mNodes) {
                List<RuleAction> actionList = mParentAction.getNestedActions(node);
                allActions.put(node, actionList);
            }

            Set<String> availableIds = computeApplicableActionIds(allActions);

            NodeProxy first = (NodeProxy) mNodes.get(0);
            String defaultId = getDefaultActionId(first);
            List<RuleAction> firstSelectedActions = allActions.get(first);

            int count = 0;
            for (RuleAction firstAction : firstSelectedActions) {
                if (!availableIds.contains(firstAction.getId())
                        && !(firstAction instanceof RuleAction.Separator)) {
                    // This action isn't supported by all selected items.
                    continue;
                }

                createContributionItem(firstAction, mNodes, defaultId).fill(menu, -1);
                count++;
            }

            if (count == 0) {
                addDisabledMessageItem("<Empty>");
            }
        }
    }

    private void applyPendingChanges() {
        LayoutCanvas canvas = mEditorDelegate.getGraphicalEditor().getCanvasControl();
        CanvasViewInfo root = canvas.getViewHierarchy().getRoot();
        if (root != null) {
            UiViewElementNode uiViewNode = root.getUiViewNode();
            NodeFactory nodeFactory = canvas.getNodeFactory();
            NodeProxy rootNode = nodeFactory.create(uiViewNode);
            if (rootNode != null) {
                rootNode.applyPendingChanges();
            }
        }
    }

    /**
     * The {@link NestedChoiceMenu} creates a lazily populated pull-right menu
     * where the items in the menu are strings
     */
    private class NestedChoiceMenu extends SubmenuAction {
        private final Choices mParentAction;
        private final List<INode> mNodes;

        NestedChoiceMenu(Choices parentAction, List<INode> nodes) {
            super(parentAction.getTitle());
            mParentAction = parentAction;
            mNodes = nodes;
        }

        @Override
        protected void addMenuItems(Menu menu) {
            List<String> titles = mParentAction.getTitles();
            List<String> ids = mParentAction.getIds();
            String current = mParentAction.getCurrent();
            assert titles.size() == ids.size();
            String[] currentValues = current != null
                    && current.indexOf(RuleAction.CHOICE_SEP) != -1 ?
                    current.split(RuleAction.CHOICE_SEP_PATTERN) : null;
            for (int i = 0, n = Math.min(titles.size(), ids.size()); i < n; i++) {
                final String id = ids.get(i);
                if (id == null || id.equals(RuleAction.SEPARATOR)) {
                    new Separator().fill(menu, -1);
                    continue;
                }

                // Find out whether this item is selected
                boolean select = false;
                if (current != null) {
                    // The current choice has a separator, so it's a flag with
                    // multiple values selected. Compare keys with the split
                    // values.
                    if (currentValues != null) {
                        if (current.indexOf(id) >= 0) {
                            for (String value : currentValues) {
                                if (id.equals(value)) {
                                    select = true;
                                    break;
                                }
                            }
                        }
                    } else {
                        // current choice has no separator, simply compare to the key
                        select = id.equals(current);
                    }
                }

                String title = titles.get(i);
                IAction a = new Action(title,
                        current != null ? IAction.AS_CHECK_BOX : IAction.AS_PUSH_BUTTON) {
                    @Override
                    public void runWithEvent(Event event) {
                        run();
                    }
                    @Override
                    public void run() {
                        String label = createActionLabel(mParentAction, mNodes);
                        mEditorDelegate.getEditor().wrapUndoEditXmlModel(label, new Runnable() {
                            @Override
                            public void run() {
                                mParentAction.getCallback().action(mParentAction, mNodes, id,
                                        Boolean.TRUE);
                                applyPendingChanges();
                            }
                        });
                    }
                };
                a.setId(id);
                a.setEnabled(true);
                if (select) {
                    a.setChecked(true);
                }

                new ActionContributionItem(a).fill(menu, -1);
            }
        }
    }
}
