/*******************************************************************************
 * Copyright (c) 2000, 2011 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.jdt.internal.ui.dialogs;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import org.eclipse.swt.SWT;
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.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ILabelProvider;

import org.eclipse.ui.dialogs.AbstractElementListSelectionDialog;
import org.eclipse.ui.dialogs.FilteredList;

import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.internal.ui.JavaUIMessages;

/**
 * A class to select elements out of a list of elements, organized on multiple
 * pages.
 */
public class MultiElementListSelectionDialog extends AbstractElementListSelectionDialog {

	private static class Page {
		private Object[] elements;
		public String filter;
		public boolean okState= false;

		public Page(Object[] elements) {
			this.elements= elements;
		}
	}

	private Page[] fPages;
	private int fCurrentPage;
	private int fNumberOfPages;

	private Button fFinishButton;
	private Button fBackButton;
	private Button fNextButton;

	private Label fPageInfoLabel;
	private String fPageInfoMessage= JavaUIMessages.MultiElementListSelectionDialog_pageInfoMessage;
	private Comparator<?> fComparator;

	/**
	 * Constructs a multi-page list selection dialog.
	 * @param parent The parent shell
	 * @param renderer the label renderer.
	 */
	public MultiElementListSelectionDialog(Shell parent, ILabelProvider renderer) {
		super(parent, renderer);
	}

	/**
	 * Sets message shown in the right top corner. Use {0} and {1} as placeholders
	 * for the current and the total number of pages.
	 * @param message the message.
	 */
	public void setPageInfoMessage(String message) {
		fPageInfoMessage= message;
	}

	/**
	 * Sets the elements to be displayed in the dialog.
	 * @param elements an array of pages holding arrays of elements
	 */
	public void setElements(Object[][] elements) {
		fNumberOfPages= elements.length;
		fPages= new Page[fNumberOfPages];
		for (int i= 0; i != fNumberOfPages; i++)
			fPages[i]= new Page(elements[i]);

		initializeResult(fNumberOfPages);
	}

	/*
	 * @see Window#open()
	 */
	@Override
	public int open() {
		List<Object[]> selection= getInitialElementSelections();
		if (selection == null || selection.size() != fNumberOfPages) {
			setInitialSelections(new Object[fNumberOfPages]);
			selection= getInitialElementSelections();
		}

		Assert.isTrue(selection.size() == fNumberOfPages);

		return super.open();
	}

	/*
	 * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(Composite)
	 */
	@Override
	protected Control createDialogArea(Composite parent) {
		Composite contents= (Composite) super.createDialogArea(parent);

		createMessageArea(contents);
		createFilterText(contents);
		createFilteredList(contents);

		fCurrentPage= 0;
		setPageData();

		applyDialogFont(contents);
		return contents;
	}

	/*
	 * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(Composite)
	 */
	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		fBackButton= createButton(parent, IDialogConstants.BACK_ID, IDialogConstants.BACK_LABEL, false);
		
		// XXX: Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=279425
		boolean HAS_BUG_279425= true;
		fNextButton= createButton(parent, IDialogConstants.NEXT_ID, IDialogConstants.NEXT_LABEL, !HAS_BUG_279425);
		fFinishButton= createButton(parent, IDialogConstants.OK_ID, IDialogConstants.FINISH_LABEL, HAS_BUG_279425);
		
		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
	}

	/*
	 * XXX: Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=279425
	 * 		The whole method can be removed once that bug is fixed.
	 * @see org.eclipse.jface.dialogs.Dialog#initializeBounds()
	 * @since 3.5.1
	 */
	@Override
	protected void initializeBounds() {
		super.initializeBounds();
		fNextButton.getShell().setDefaultButton(fNextButton);
	}

	/*
	 * @see org.eclipse.ui.dialogs.SelectionDialog#createMessageArea(Composite)
	 */
	@Override
	protected Label createMessageArea(Composite parent) {
		Composite composite= new Composite(parent, SWT.NONE);

		GridLayout layout= new GridLayout();
		layout.marginHeight= 0;
		layout.marginWidth= 0;
		layout.horizontalSpacing= 5;
		layout.numColumns= 2;
		composite.setLayout(layout);

		GridData data= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		composite.setLayoutData(data);

		Label messageLabel= super.createMessageArea(composite);

		fPageInfoLabel= new Label(composite, SWT.NULL);
		fPageInfoLabel.setText(getPageInfoMessage());

		data= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		data.horizontalAlignment= GridData.END;
		fPageInfoLabel.setLayoutData(data);
		applyDialogFont(messageLabel);
		return messageLabel;
	}

	/*
	 * @see org.eclipse.ui.dialogs.SelectionStatusDialog#computeResult()
	 */
	@Override
	protected void computeResult() {
		setResult(fCurrentPage, getSelectedElements());
	}

	/*
	 * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int)
	 */
	@Override
	protected void buttonPressed(int buttonId) {
		if (buttonId == IDialogConstants.BACK_ID) {
			turnPage(false);
		} else if (buttonId == IDialogConstants.NEXT_ID) {
			turnPage(true);
		} else {
			super.buttonPressed(buttonId);
		}
	}

	/**
	 * @see AbstractElementListSelectionDialog#handleDefaultSelected()
	 */
	@Override
	protected void handleDefaultSelected() {
		if (validateCurrentSelection()) {
			if (fCurrentPage == fNumberOfPages - 1) {
				buttonPressed(IDialogConstants.OK_ID);
			} else {
				buttonPressed(IDialogConstants.NEXT_ID);
			}
		}
	}

	/**
	 * @see AbstractElementListSelectionDialog#updateButtonsEnableState(IStatus)
	 */
	@Override
	protected void updateButtonsEnableState(IStatus status) {
		boolean isOK= !status.matches(IStatus.ERROR);
		fPages[fCurrentPage].okState= isOK;

		boolean isAllOK= isOK;
		for (int i= 0; i != fNumberOfPages; i++)
			isAllOK = isAllOK && fPages[i].okState;

		fFinishButton.setEnabled(isAllOK);

		boolean nextButtonEnabled= isOK && (fCurrentPage < fNumberOfPages - 1);

		fNextButton.setEnabled(nextButtonEnabled);
		fBackButton.setEnabled(fCurrentPage != 0);

		if (nextButtonEnabled) {
			getShell().setDefaultButton(fNextButton);
		} else if (isAllOK) {
			getShell().setDefaultButton(fFinishButton);
		}
	}

	private void turnPage(boolean toNextPage) {
		Page page= fPages[fCurrentPage];

		// store filter
		String filter= getFilter();
		if (filter == null)
			filter= ""; //$NON-NLS-1$
		page.filter= filter;

		// store selection
		Object[] selectedElements= getSelectedElements();
		List<Object[]> list= getInitialElementSelections();
		list.set(fCurrentPage, selectedElements);

		// store result
		setResult(fCurrentPage, getSelectedElements());

		if (toNextPage) {
			if (fCurrentPage + 1 >= fNumberOfPages)
				return;

			fCurrentPage++;
		} else {
			if (fCurrentPage - 1 < 0)
				return;

			fCurrentPage--;
		}

		if (fPageInfoLabel != null && !fPageInfoLabel.isDisposed())
			fPageInfoLabel.setText(getPageInfoMessage());

		setPageData();

		validateCurrentSelection();
	}

	private void setPageData() {
		Page page= fPages[fCurrentPage];

		// 1. set elements
		setListElements(page.elements);

		// 2. apply filter
		String filter= page.filter;
		if (filter == null)
			filter= ""; //$NON-NLS-1$
		setFilter(filter);

		// 3. select elements
		Object[] selectedElements= (Object[]) getInitialElementSelections().get(fCurrentPage);
		setSelection(selectedElements);
		fFilteredList.setFocus();
	}

	private String getPageInfoMessage() {
		if (fPageInfoMessage == null)
			return ""; //$NON-NLS-1$

		String[] args= new String[] { Integer.toString(fCurrentPage + 1), Integer.toString(fNumberOfPages) };
		return Messages.format(fPageInfoMessage, args);
	}

	private void initializeResult(int length) {
		List<Object> result= new ArrayList<Object>(length);
		for (int i= 0; i != length; i++)
			result.add(null);

		setResult(result);
	}

	/**
	 * Gets the current Page.
	 * @return Returns a int
	 */
	public int getCurrentPage() {
		return fCurrentPage;
	}

	/**
	 * Set the <code>Comparator</code> used to sort
	 * the elements in the List.
	 *
	 * @param comparator the comparator to use, not null.
	 */
	public void setComparator(Comparator<?> comparator) {
		fComparator= comparator;
		if (fFilteredList != null)
			fFilteredList.setComparator(fComparator);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected FilteredList createFilteredList(Composite parent) {
		FilteredList filteredList= super.createFilteredList(parent);
		if (fComparator != null) {
			filteredList.setComparator(fComparator);
		}
		return filteredList;
	}

}
