/*******************************************************************************
 * Copyright (c) 2000, 2006 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.ide.dialogs;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import org.eclipse.core.filesystem.IFileInfo;
import org.eclipse.core.resources.IPathVariableManager;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.plugin.AbstractUIPlugin;

/**
 * A widget group that displays path variables. 
 * Includes buttons to edit, remove existing variables and create new ones.
 * 
 * @since 2.1
 */
public class PathVariablesGroup {
    /**
     * Simple data structure that holds a path variable name/value pair.
     */
    public static class PathVariableElement {
        /**
         * The name of the element.
         */
        public String name;

        /**
         * The path of the element.
         */
        public IPath path;
    }

    // sizing constants
    private static final int SIZING_SELECTION_PANE_WIDTH = 400;

    // parent shell
    private Shell shell;

    private Label variableLabel;

    private Table variableTable;

    private Button addButton;

    private Button editButton;

    private Button removeButton;

    // used to compute layout sizes
    private FontMetrics fontMetrics;

    // create a multi select table
    private boolean multiSelect;

    // IResource.FILE and/or IResource.FOLDER
    private int variableType;

    // External listener called when the table selection changes
    private Listener selectionListener;

    // temporary collection for keeping currently defined variables
    private SortedMap tempPathVariables;

    // set of removed variables' names
    private Set removedVariableNames;

    // reference to the workspace's path variable manager
    private IPathVariableManager pathVariableManager;

    // file image
    private final Image FILE_IMG = PlatformUI.getWorkbench().getSharedImages()
            .getImage(ISharedImages.IMG_OBJ_FILE);

    // folder image
    private final Image FOLDER_IMG = PlatformUI.getWorkbench()
            .getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER);

    // unknown (non-existent) image. created locally, dispose locally
    private Image imageUnkown;

    /**
     * Creates a new PathVariablesGroup.
     *
     * @param multiSelect create a multi select tree
     * @param variableType the type of variables that are displayed in 
     * 	the widget group. <code>IResource.FILE</code> and/or <code>IResource.FOLDER</code>
     * 	logically ORed together.
     */
    public PathVariablesGroup(boolean multiSelect, int variableType) {
        this.multiSelect = multiSelect;
        this.variableType = variableType;
        pathVariableManager = ResourcesPlugin.getWorkspace()
                .getPathVariableManager();
        removedVariableNames = new HashSet();
        tempPathVariables = new TreeMap();
        // initialize internal model
        initTemporaryState();
    }

    /**
     * Creates a new PathVariablesGroup.
     *
     * @param multiSelect create a multi select tree
     * @param variableType the type of variables that are displayed in 
     * 	the widget group. <code>IResource.FILE</code> and/or <code>IResource.FOLDER</code>
     * 	logically ORed together.
     * @param selectionListener listener notified when the selection changes
     * 	in the variables list.
     */
    public PathVariablesGroup(boolean multiSelect, int variableType,
            Listener selectionListener) {
        this(multiSelect, variableType);
        this.selectionListener = selectionListener;
    }

    /**
     * Opens a dialog for creating a new variable.
     */
    private void addNewVariable() {
        // constructs a dialog for editing the new variable's current name and value
        PathVariableDialog dialog = new PathVariableDialog(shell,
                PathVariableDialog.NEW_VARIABLE, variableType,
                pathVariableManager, tempPathVariables.keySet());

        // opens the dialog - just returns if the user cancels it
        if (dialog.open() == Window.CANCEL) {
			return;
		}

        // otherwise, adds the new variable (or updates an existing one) in the
        // temporary collection of currently defined variables
        String newVariableName = dialog.getVariableName();
        IPath newVariableValue = new Path(dialog.getVariableValue());
        tempPathVariables.put(newVariableName, newVariableValue);

        // the UI must be updated
        updateWidgetState(newVariableName);
    }

    /**
     * Creates the widget group.
     * Callers must call <code>dispose</code> when the group is no 
     * longer needed.
     * 
     * @param parent the widget parent
     * @return container of the widgets 
     */
    public Control createContents(Composite parent) {
        Font font = parent.getFont();

        if (imageUnkown == null) {
            ImageDescriptor descriptor = AbstractUIPlugin
                    .imageDescriptorFromPlugin(
                            IDEWorkbenchPlugin.IDE_WORKBENCH,
                            "$nl$/icons/full/obj16/warning.gif"); //$NON-NLS-1$
            imageUnkown = descriptor.createImage();
        }
        initializeDialogUnits(parent);
        shell = parent.getShell();

        // define container & its layout
        Composite pageComponent = new Composite(parent, SWT.NULL);
        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        layout.marginWidth = 0;
        layout.marginHeight = 0;
        pageComponent.setLayout(layout);
        GridData data = new GridData(GridData.FILL_BOTH);
        data.widthHint = SIZING_SELECTION_PANE_WIDTH;
        pageComponent.setLayoutData(data);
        pageComponent.setFont(font);

        // layout the table & its buttons
        variableLabel = new Label(pageComponent, SWT.LEFT);
        variableLabel.setText(IDEWorkbenchMessages.PathVariablesBlock_variablesLabel);
        data = new GridData();
        data.horizontalAlignment = GridData.FILL;
        data.horizontalSpan = 2;
        variableLabel.setLayoutData(data);
        variableLabel.setFont(font);

        int tableStyle = SWT.BORDER | SWT.FULL_SELECTION;
        if (multiSelect) {
            tableStyle |= SWT.MULTI;
        }
        variableTable = new Table(pageComponent, tableStyle);
        variableTable.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                updateEnabledState();
                if (selectionListener != null) {
					selectionListener.handleEvent(new Event());
				}
            }
        });
        data = new GridData(GridData.FILL_BOTH);
        data.heightHint = variableTable.getItemHeight() * 7;
        variableTable.setLayoutData(data);
        variableTable.setFont(font);

        createButtonGroup(pageComponent);
        // populate table with current internal state and set buttons' initial state
        updateWidgetState(null);

        return pageComponent;
    }

    /**
     * Disposes the group's resources. 
     */
    public void dispose() {
        if (imageUnkown != null) {
            imageUnkown.dispose();
            imageUnkown = null;
        }
    }

    /**
     * Opens a dialog for editing an existing variable.
     *
     * @see PathVariableDialog
     */
    private void editSelectedVariable() {
        // retrieves the name and value for the currently selected variable
        TableItem item = variableTable.getItem(variableTable
                .getSelectionIndex());
        String variableName = (String) item.getData();
        IPath variableValue = (IPath) tempPathVariables.get(variableName);

        // constructs a dialog for editing the variable's current name and value
        PathVariableDialog dialog = new PathVariableDialog(shell,
                PathVariableDialog.EXISTING_VARIABLE, variableType,
                pathVariableManager, tempPathVariables.keySet());
        dialog.setVariableName(variableName);
        dialog.setVariableValue(variableValue.toOSString());

        // opens the dialog - just returns if the user cancels it
        if (dialog.open() == Window.CANCEL) {
			return;
		}

        // the name can be changed, so we remove the current variable definition...
        removedVariableNames.add(variableName);
        tempPathVariables.remove(variableName);

        String newVariableName = dialog.getVariableName();
        IPath newVariableValue = new Path(dialog.getVariableValue());

        // and add it again (maybe with a different name)
        tempPathVariables.put(newVariableName, newVariableValue);

        // now we must refresh the UI state
        updateWidgetState(newVariableName);

    }

    /**
     * Returns the enabled state of the group's widgets.
     * Returns <code>true</code> if called prior to calling 
     * <code>createContents</code>.
     * 
     * @return boolean the enabled state of the group's widgets.
     * 	 <code>true</code> if called prior to calling <code>createContents</code>.
     */
    public boolean getEnabled() {
        if (variableTable != null && !variableTable.isDisposed()) {
            return variableTable.getEnabled();
        }
        return true;
    }

    /**
     * Returns the selected variables.
     *  
     * @return the selected variables. Returns an empty array if 
     * 	the widget group has not been created yet by calling 
     * 	<code>createContents</code>
     */
    public PathVariableElement[] getSelection() {
        if (variableTable == null) {
            return new PathVariableElement[0];
        }
        TableItem[] items = variableTable.getSelection();
        PathVariableElement[] selection = new PathVariableElement[items.length];

        for (int i = 0; i < items.length; i++) {
            String name = (String) items[i].getData();
            selection[i] = new PathVariableElement();
            selection[i].name = name;
            selection[i].path = (IPath) tempPathVariables.get(name);
        }
        return selection;
    }

    /**
     * Creates the add/edit/remove buttons
     * 
     * @param parent the widget parent
     */
    private void createButtonGroup(Composite parent) {
        Font font = parent.getFont();
        Composite groupComponent = new Composite(parent, SWT.NULL);
        GridLayout groupLayout = new GridLayout();
        groupLayout.marginWidth = 0;
        groupLayout.marginHeight = 0;
        groupComponent.setLayout(groupLayout);
        GridData data = new GridData();
        data.verticalAlignment = GridData.FILL;
        data.horizontalAlignment = GridData.FILL;
        groupComponent.setLayoutData(data);
        groupComponent.setFont(font);

        addButton = new Button(groupComponent, SWT.PUSH);
        addButton.setText(IDEWorkbenchMessages.PathVariablesBlock_addVariableButton);
        addButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                addNewVariable();
            }
        });
        addButton.setFont(font);
        setButtonLayoutData(addButton);

        editButton = new Button(groupComponent, SWT.PUSH);
        editButton.setText(IDEWorkbenchMessages.PathVariablesBlock_editVariableButton);
        editButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                editSelectedVariable();
            }
        });
        editButton.setFont(font);
        setButtonLayoutData(editButton);

        removeButton = new Button(groupComponent, SWT.PUSH);
        removeButton.setText(IDEWorkbenchMessages.PathVariablesBlock_removeVariableButton);
        removeButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                removeSelectedVariables();
            }
        });
        removeButton.setFont(font);
        setButtonLayoutData(removeButton);
    }

    /**
     * Initializes the computation of horizontal and vertical dialog units
     * based on the size of current font.
     * <p>
     * This method must be called before <code>setButtonLayoutData</code> 
     * is called.
     * </p>
     *
     * @param control a control from which to obtain the current font
     */
    protected void initializeDialogUnits(Control control) {
        // Compute and store a font metric
        GC gc = new GC(control);
        gc.setFont(control.getFont());
        fontMetrics = gc.getFontMetrics();
        gc.dispose();
    }

    /**
     * (Re-)Initialize collections used to mantain temporary variable state.
     */
    private void initTemporaryState() {
        String[] varNames = pathVariableManager.getPathVariableNames();

        tempPathVariables.clear();
        for (int i = 0; i < varNames.length; i++) {
            IPath value = pathVariableManager.getValue(varNames[i]);

            // the value may not exist any more
            if (value != null) {
                boolean isFile = value.toFile().isFile();
                if ((isFile && (variableType & IResource.FILE) != 0)
                        || (isFile == false && (variableType & IResource.FOLDER) != 0)) {

                    tempPathVariables.put(varNames[i], value);
                }
            }
        }
        removedVariableNames.clear();
    }

    /**
     * Updates button enabled state, depending on the number of currently selected
     * variables in the table.
     */
    private void updateEnabledState() {
        int itemsSelectedCount = variableTable.getSelectionCount();
        editButton.setEnabled(itemsSelectedCount == 1);
        removeButton.setEnabled(itemsSelectedCount > 0);
    }

    /**
     * Rebuilds table widget state with the current list of variables (reflecting
     * any changes, additions and removals), and selects the item corresponding to
     * the given variable name. If the variable name is <code>null</code>, the
     * first item (if any) will be selected.
     * 
     * @param selectedVarName the name for the variable to be selected (may be
     * <code>null</code>)
     * @see IPathVariableManager#getPathVariableNames()
     * @see IPathVariableManager#getValue(String)
     */
    private void updateVariableTable(String selectedVarName) {
        variableTable.removeAll();
        int selectedVarIndex = 0;
        for (Iterator varNames = tempPathVariables.keySet().iterator(); varNames
                .hasNext();) {
            TableItem item = new TableItem(variableTable, SWT.NONE);
            String varName = (String) varNames.next();
            IPath value = (IPath) tempPathVariables.get(varName);
            IFileInfo file = IDEResourceInfoUtils.getFileInfo(value);

            item.setText(varName + " - " + value.toOSString()); //$NON-NLS-1$ 
            // the corresponding variable name is stored in each table widget item
            item.setData(varName);
            item.setImage(file.exists() ? (file.isDirectory() ? FOLDER_IMG 
                    : FILE_IMG ) : imageUnkown);
            if (varName.equals(selectedVarName)) {
				selectedVarIndex = variableTable.getItemCount() - 1;
			}
        }
        if (variableTable.getItemCount() > selectedVarIndex) {
            variableTable.setSelection(selectedVarIndex);
            if (selectionListener != null) {
				selectionListener.handleEvent(new Event());
			}
        } else if (variableTable.getItemCount() == 0
                && selectionListener != null) {
			selectionListener.handleEvent(new Event());
		}
    }

    /**
     * Commits the temporary state to the path variable manager in response to user
     * confirmation.
     * @return boolean <code>true</code> if there were no problems.
     * @see IPathVariableManager#setValue(String, IPath)
     */
    public boolean performOk() {
        try {
            // first process removed variables  
            for (Iterator removed = removedVariableNames.iterator(); removed
                    .hasNext();) {
                String removedVariableName = (String) removed.next();
                // only removes variables that have not been added again
                if (!tempPathVariables.containsKey(removedVariableName)) {
					pathVariableManager.setValue(removedVariableName, null);
				}
            }

            // then process the current collection of variables, adding/updating them
            for (Iterator current = tempPathVariables.entrySet().iterator(); current
                    .hasNext();) {
                Map.Entry entry = (Map.Entry) current.next();
                String variableName = (String) entry.getKey();
                IPath variableValue = (IPath) entry.getValue();
                pathVariableManager.setValue(variableName, variableValue);
            }
            // re-initialize temporary state
            initTemporaryState();

            // performOk accepted
            return true;
        } catch (CoreException ce) {
            ErrorDialog.openError(shell, null, null, ce.getStatus());
        }
        return false;
    }

    /**
     * Removes the currently selected variables.
     */
    private void removeSelectedVariables() {
        // remove each selected element
        int[] selectedIndices = variableTable.getSelectionIndices();
        for (int i = 0; i < selectedIndices.length; i++) {
            TableItem selectedItem = variableTable.getItem(selectedIndices[i]);
            String varName = (String) selectedItem.getData();
            removedVariableNames.add(varName);
            tempPathVariables.remove(varName);
        }
        updateWidgetState(null);
    }

    /**
     * Sets the <code>GridData</code> on the specified button to
     * be one that is spaced for the current dialog page units. The
     * method <code>initializeDialogUnits</code> must be called once
     * before calling this method for the first time.
     *
     * @param button the button to set the <code>GridData</code>
     * @return the <code>GridData</code> set on the specified button
     */
    private GridData setButtonLayoutData(Button button) {
        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        int widthHint = Dialog.convertHorizontalDLUsToPixels(fontMetrics,
                IDialogConstants.BUTTON_WIDTH);
        data.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT,
                SWT.DEFAULT, true).x);
        button.setLayoutData(data);
        return data;
    }

    /**
     * Sets the enabled state of the group's widgets.
     * Does nothing if called prior to calling <code>createContents</code>.
     * 
     * @param enabled the new enabled state of the group's widgets
     */
    public void setEnabled(boolean enabled) {
        if (variableTable != null && !variableTable.isDisposed()) {
            variableLabel.setEnabled(enabled);
            variableTable.setEnabled(enabled);
            addButton.setEnabled(enabled);
            if (enabled) {
				updateEnabledState();
			} else {
                editButton.setEnabled(enabled);
                removeButton.setEnabled(enabled);
            }
        }
    }

    /**
     * Updates the widget's current state: refreshes the table with the current 
     * defined variables, selects the item corresponding to the given variable 
     * (selects the first item if <code>null</code> is provided) and updates 
     * the enabled state for the Add/Remove/Edit buttons.
     * 
     * @param selectedVarName the name of the variable to be selected (may be null)
     */
    private void updateWidgetState(String selectedVarName) {
        updateVariableTable(selectedVarName);
        updateEnabledState();
    }
}
