/*******************************************************************************
 * Copyright (c) 2000, 2008 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 
 *  	Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog
 *      font should be activated and used by other components.
 *******************************************************************************/
package org.eclipse.ui.internal.dialogs;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.core.runtime.IBundleGroup;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.internal.ConfigureColumnsDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
import org.eclipse.ui.internal.WorkbenchMessages;
import org.eclipse.ui.internal.about.AboutBundleGroupData;
import org.eclipse.ui.internal.about.AboutData;
import org.osgi.framework.Bundle;

/**
 * Displays information about the product plugins.
 *
 * PRIVATE
 *	This class is internal to the workbench and must not be called outside
 *	the workbench.
 */
public class AboutFeaturesDialog extends ProductInfoDialog {

    /**
     * Table height in dialog units (value 150).
     */
    private static final int TABLE_HEIGHT = 150;

    private static final int INFO_HEIGHT = 100;

    private final static int MORE_ID = IDialogConstants.CLIENT_ID + 1;

    private final static int PLUGINS_ID = IDialogConstants.CLIENT_ID + 2;

    private final static int COLUMNS_ID = IDialogConstants.CLIENT_ID + 3;

    private Table table;

    private Label imageLabel;

    private StyledText text;

    private Composite infoArea;

    private Map cachedImages = new HashMap();

    private String columnTitles[] = {
            WorkbenchMessages.AboutFeaturesDialog_provider,
            WorkbenchMessages.AboutFeaturesDialog_featureName, 
            WorkbenchMessages.AboutFeaturesDialog_version, 
            WorkbenchMessages.AboutFeaturesDialog_featureId, 
    };

    private String productName;

    private AboutBundleGroupData[] bundleGroupInfos;

    private int lastColumnChosen = 0; // initially sort by provider

    private boolean reverseSort = false; // initially sort ascending

    private AboutBundleGroupData lastSelection = null;

    private Button moreButton;

    private Button pluginsButton;

    private static Map featuresMap;

    /**
     * Constructor for AboutFeaturesDialog.
     * 
     * @param parentShell the parent shell
     * @param productName the product name
     * @param bundleGroupInfos the bundle info
     */
    public AboutFeaturesDialog(Shell parentShell, String productName,
            AboutBundleGroupData[] bundleGroupInfos) {
        super(parentShell);
        this.productName = productName;

        // the order of the array may be changed due to sorting, so create a
        // copy
        this.bundleGroupInfos = new AboutBundleGroupData[bundleGroupInfos.length];
        System.arraycopy(bundleGroupInfos, 0, this.bundleGroupInfos, 0,
                bundleGroupInfos.length);

        AboutData.sortByProvider(reverseSort, this.bundleGroupInfos);
    }

    /**
     * The More Info button was pressed.  Open a browser with the license for the
     * selected item or an information dialog if there is no license, or the browser
     * cannot be opened. 
     */
    private void handleMoreInfoPressed() {
        TableItem[] items = table.getSelection();
        if (items.length <= 0) {
			return;
		}

        AboutBundleGroupData info = (AboutBundleGroupData) items[0].getData();
        if (info == null || !openBrowser(info.getLicenseUrl())) {
            MessageDialog.openInformation(getShell(), WorkbenchMessages.AboutFeaturesDialog_noInfoTitle, 
                    WorkbenchMessages.AboutFeaturesDialog_noInformation);
        }
    }

    /**
     * The Plugins button was pressed. Open an about dialog on the plugins for
     * the selected feature.
     */
    private void handlePluginInfoPressed() {
        TableItem[] items = table.getSelection();
        if (items.length <= 0) {
			return;
		}

        AboutBundleGroupData info = (AboutBundleGroupData) items[0].getData();
        IBundleGroup bundleGroup = info.getBundleGroup();
        Bundle[] bundles = bundleGroup == null ? new Bundle[0] : bundleGroup
                .getBundles();

        AboutPluginsDialog d = new AboutPluginsDialog(getShell(), productName,
                bundles, WorkbenchMessages.AboutFeaturesDialog_pluginInfoTitle, 
                NLS.bind(WorkbenchMessages.AboutFeaturesDialog_pluginInfoMessage, bundleGroup.getIdentifier()),
                IWorkbenchHelpContextIds.ABOUT_FEATURES_PLUGINS_DIALOG);
        d.open();
    }

    /*
     * (non-Javadoc) Method declared on Dialog.
     */
    protected void buttonPressed(int buttonId) {
        switch (buttonId) {
        case MORE_ID:
            handleMoreInfoPressed();
            break;
        case PLUGINS_ID:
            handlePluginInfoPressed();
            break;
        case COLUMNS_ID:
        	handleColumnsPressed();
        	break;
        default:
            super.buttonPressed(buttonId);
            break;
        }
    }

    /**
	 * 
	 */
	private void handleColumnsPressed() {
		ConfigureColumnsDialog d = new ConfigureColumnsDialog(this, table);
		d.open();
	}

	/*
     * (non-Javadoc) Method declared on Window.
     */
    protected void configureShell(Shell newShell) {
        super.configureShell(newShell);
        if (productName != null) {
			newShell.setText(NLS.bind(WorkbenchMessages.AboutFeaturesDialog_shellTitle, productName));
		}

        PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell,
				IWorkbenchHelpContextIds.ABOUT_FEATURES_DIALOG);
    }

    /**
     * Add buttons to the dialog's button bar.
     * 
     * Subclasses should override.
     * 
     * @param parent
     *            the button bar composite
     */
    protected void createButtonsForButtonBar(Composite parent) {
        parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        moreButton = createButton(parent, MORE_ID, WorkbenchMessages.AboutFeaturesDialog_moreInfo, false);
        pluginsButton = createButton(parent, PLUGINS_ID, WorkbenchMessages.AboutFeaturesDialog_pluginsInfo, false); 
        createButton(parent, COLUMNS_ID, WorkbenchMessages.AboutFeaturesDialog_columns, false); 
        Label l = new Label(parent, SWT.NONE);
        l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        GridLayout layout = (GridLayout) parent.getLayout();
        layout.numColumns++;
        layout.makeColumnsEqualWidth = false;

        Button b = createButton(parent, IDialogConstants.OK_ID,
                IDialogConstants.OK_LABEL, true);
        b.setFocus();

        TableItem[] items = table.getSelection();
        if (items.length > 0) {
			updateButtons((AboutBundleGroupData) items[0].getData());
		}
    }

    /**
     * Create the contents of the dialog (above the button bar).
     * 
     * Subclasses should overide.
     * 
     * @param parent  the parent composite to contain the dialog area
     * @return the dialog area control
     */
    protected Control createDialogArea(Composite parent) {
        setHandCursor(new Cursor(parent.getDisplay(), SWT.CURSOR_HAND));
        setBusyCursor(new Cursor(parent.getDisplay(), SWT.CURSOR_WAIT));
        getShell().addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent e) {
                if (getHandCursor() != null) {
					getHandCursor().dispose();
				}
                if (getBusyCursor() != null) {
					getBusyCursor().dispose();
				}
            }
        });

        Composite outer = (Composite) super.createDialogArea(parent);

        createTable(outer);
        createInfoArea(outer);
        
        return outer;
    }

    /** 
     * Create the info area containing the image and text
     */
    protected void createInfoArea(Composite parent) {
        Font font = parent.getFont();

        infoArea = new Composite(parent, SWT.NULL);
        GridData data = new GridData(GridData.FILL, GridData.FILL, true, true);
        // need to provide space for arbitrary feature infos, not just the
        // one selected by default
        data.heightHint = convertVerticalDLUsToPixels(INFO_HEIGHT);
        infoArea.setLayoutData(data);

        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        infoArea.setLayout(layout);

        imageLabel = new Label(infoArea, SWT.NONE);
        data = new GridData(GridData.FILL, GridData.BEGINNING, false, false);
        data.widthHint = 32;
        data.heightHint = 32;
        imageLabel.setLayoutData(data);
        imageLabel.setFont(font);

        // text on the right
        text = new StyledText(infoArea, SWT.MULTI | SWT.READ_ONLY);
        text.setCaret(null);
        text.setFont(parent.getFont());
        data = new GridData(GridData.FILL, GridData.FILL, true, true);
        text.setLayoutData(data);
        text.setFont(font);
        text.setCursor(null);
        text.setBackground(infoArea.getBackground());
        addListeners(text);

        TableItem[] items = table.getSelection();
        if (items.length > 0) {
			updateInfoArea((AboutBundleGroupData) items[0].getData());
		}
    }

    /**
     * Create the table part of the dialog.
     *
     * @param parent  the parent composite to contain the dialog area
     */
    protected void createTable(Composite parent) {
        table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE
                | SWT.FULL_SELECTION | SWT.BORDER);
        
        GridData gridData = new GridData(GridData.FILL, GridData.FILL, true,
                true);
        gridData.heightHint = convertVerticalDLUsToPixels(TABLE_HEIGHT);
        table.setLayoutData(gridData);
        table.setHeaderVisible(true);
        
        table.setLinesVisible(true);
        table.setFont(parent.getFont());
        table.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                AboutBundleGroupData info = (AboutBundleGroupData) e.item
                        .getData();
                updateInfoArea(info);
                updateButtons(info);
            }
        });
        
        int[] columnWidths = { convertHorizontalDLUsToPixels(120),
                convertHorizontalDLUsToPixels(120),
                convertHorizontalDLUsToPixels(70),
                convertHorizontalDLUsToPixels(130) };

        for (int i = 0; i < columnTitles.length; i++) {
            TableColumn tableColumn = new TableColumn(table, SWT.NULL);
            tableColumn.setWidth(columnWidths[i]);
            tableColumn.setText(columnTitles[i]);
            final int columnIndex = i;
            tableColumn.addSelectionListener(new SelectionAdapter() {
                public void widgetSelected(SelectionEvent e) {
                    sort(columnIndex);
                }
            });
        }

        // create a table row for each bundle group
        String selId = lastSelection == null ? null : lastSelection.getId();
        int sel = 0;
        for (int i = 0; i < bundleGroupInfos.length; i++) {
            if (bundleGroupInfos[i].getId().equals(selId)) {
				sel = i;
			}

            TableItem item = new TableItem(table, SWT.NULL);
            item.setText(createRow(bundleGroupInfos[i]));
            item.setData(bundleGroupInfos[i]);
        }

        // if an item was specified during construction, it should be
        // selected when the table is created
        if (bundleGroupInfos.length > 0) {
            table.setSelection(sel);
            table.showSelection();
        }
    }

    /**
     * @see Window#close()
     */
    public boolean close() {
        boolean ret = super.close();

        Iterator iter = cachedImages.values().iterator();
        while (iter.hasNext()) {
            Image image = (Image) iter.next();
            image.dispose();
        }

        return ret;
    }

    /**
     * Update the button enablement
     */
    private void updateButtons(AboutBundleGroupData info) {
        if (info == null) {
            moreButton.setEnabled(false);
            pluginsButton.setEnabled(false);
            return;
        }

        // Creating the feature map is too much just to determine enablement, so if
        // it doesn't already exist, just enable the buttons.  If this was the wrong
        // choice, then when the button is actually pressed an dialog will be opened. 
        if (featuresMap == null) {
            moreButton.setEnabled(true);
            pluginsButton.setEnabled(true);
            return;
        }

        moreButton.setEnabled(info.getLicenseUrl() != null);
        pluginsButton.setEnabled(true);
    }

    /**
     * Update the info area
     */
    private void updateInfoArea(AboutBundleGroupData info) {
        if (info == null) {
            imageLabel.setImage(null);
            text.setText(""); //$NON-NLS-1$
            return;
        }

        ImageDescriptor desc = info.getFeatureImage();
        Image image = (Image) cachedImages.get(desc);
        if (image == null && desc != null) {
            image = desc.createImage();
            cachedImages.put(desc, image);
        }
        imageLabel.setImage(image);

        String aboutText = info.getAboutText();
        setItem(null);
        if (aboutText != null) {
			setItem(scan(aboutText));
		}

        if (getItem() == null) {
			text.setText(WorkbenchMessages.AboutFeaturesDialog_noInformation);
		} else {
            text.setText(getItem().getText());
            text.setCursor(null);
            setLinkRanges(text, getItem().getLinkRanges());
        }
    }

    /**
     * Select the initial selection
     * 
     * @param info the info
     */
    public void setInitialSelection(AboutBundleGroupData info) {
        lastSelection = info;
    }

    /**
     * Sort the rows of the table based on the selected column.
     * 
     * @param column
     *            index of table column selected as sort criteria
     */
    private void sort(int column) {
        if (lastColumnChosen == column) {
			reverseSort = !reverseSort;
		} else {
            reverseSort = false;
            lastColumnChosen = column;
        }

        if (table.getItemCount() <= 1) {
			return;
		}

        // Remember the last selection
        int sel = table.getSelectionIndex();
        if (sel != -1) {
			lastSelection = bundleGroupInfos[sel];
		}

        switch (column) {
        case 0:
            AboutData.sortByProvider(reverseSort, bundleGroupInfos);
            break;
        case 1:
            AboutData.sortByName(reverseSort, bundleGroupInfos);
            break;
        case 2:
            AboutData.sortByVersion(reverseSort, bundleGroupInfos);
            break;
        case 3:
            AboutData.sortById(reverseSort, bundleGroupInfos);
            break;
        }

        refreshTable();
    }

    /**
     * Refresh the rows of the table based on the selected column. Maintain
     * selection from before sort action request.
     */
    private void refreshTable() {
        TableItem[] items = table.getItems();

        // create new order of table items
        for (int i = 0; i < items.length; i++) {
            items[i].setText(createRow(bundleGroupInfos[i]));
            items[i].setData(bundleGroupInfos[i]);
        }

        // Maintain the original selection
        int sel = -1;
        if (lastSelection != null) {
            String oldId = lastSelection.getId();
            for (int k = 0; k < bundleGroupInfos.length; k++) {
				if (oldId.equalsIgnoreCase(bundleGroupInfos[k].getId())) {
					sel = k;
				}
			}

            table.setSelection(sel);
            table.showSelection();
        }

        updateInfoArea(lastSelection);
    }

    /**
     * Return an array of strings containing the argument's information in the
     * proper order for this table's columns.
     * 
     * @param info
     *            the source information for the new row, must not be null
     */
    private static String[] createRow(AboutBundleGroupData info) {
        return new String[] { info.getProviderName(), info.getName(),
                info.getVersion(), info.getId() };
    }
}
