/*******************************************************************************
 * Copyright (c) 2006, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Valentin Ciocoi - Bug 393700 - [Export breakpoints] Wrong file appears in overwrite dialog and wrong file can be overwritten
 *******************************************************************************/

package org.eclipse.debug.internal.ui.importexport.breakpoints;

import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.internal.core.IInternalDebugCoreConstants;
import org.eclipse.debug.internal.ui.IDebugHelpContextIds;
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
import org.eclipse.debug.internal.ui.SWTFactory;
import org.eclipse.debug.internal.ui.views.breakpoints.BreakpointsViewer;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.actions.ExportBreakpointsOperation;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.PlatformUI;

/**
 * <p>
 * This class provides an internal implementation of a WizardPage, which is used
 * in the Export Breakpoints wizard.
 * </p>
 * <p>
 * The implementation presents the breakpoints to the user as they are shown in
 * their current breakpoint view.
 * </p>
 * <p>
 * Possible extensions would include:
 * <ul>
 * <li> Able to change the views as in the breakpoints view itself
 * <li> Able to reorder groups from within the wizard - easier in the viewer itself though
 * </ul>
 * </p>
 * This class is used by <code>WizardExportBreakpoints</code>
 *
 * @since 3.2
 */
public class WizardExportBreakpointsPage extends WizardPage implements Listener {

	// widgets
	private Button fOverwriteExistingFilesCheckbox = null;
	private Text fDestinationNameField = null;
	private Button fDestinationBrowseButton = null;
	private EmbeddedBreakpointsViewer fTView = null;
	private IStructuredSelection fSelection = null;
	private Button fSelectAll = null;
	private Button fDeselectAll = null;

	//state constants
	private static final String OVERWRITE_ALL_STATE = "overwrite"; //$NON-NLS-1$
	private static final String DESTINATION_FILE_NAME = "filename"; //$NON-NLS-1$

	/**
	 * This is the default constructor. It accepts the name for the tab as a
	 * parameter and an existing selection
	 *
	 * @param pageName the name of the page
	 */
	public WizardExportBreakpointsPage(String pageName, IStructuredSelection selection) {
		super(pageName, ImportExportMessages.WizardExportBreakpoints_0, null);
		fSelection = selection;
	}

	@Override
	public void handleEvent(Event event) {
		Widget source = event.widget;
		if (source == fDestinationBrowseButton) {
			handleDestinationBrowseButtonPressed();
		}
		else if (source == fDestinationNameField) {
			handlePathTextModifiedEvent();
		}
		else if(source == fSelectAll) {
			handleSelectAllPressed();
		}
		else if(source == fDeselectAll) {
			handleDeselectAllPressed();
		}
	}

	/**
	 * Handles the select all button pressed
	 *
	 */
	private void handleSelectAllPressed() {
		BreakpointsViewer viewer = fTView.getViewer();
		viewer.getTree().selectAll();
		viewer.setCheckedElements(viewer.getStructuredSelection().toArray());
		viewer.setGrayedElements(new Object[] {});
		viewer.getTree().deselectAll();
		setPageComplete(detectPageComplete());
	}

	/**
	 * Handles the de-select all button pressed
	 *
	 */
	private void handleDeselectAllPressed() {
		BreakpointsViewer viewer = fTView.getViewer();
		viewer.setCheckedElements(new Object[] {});
		viewer.setGrayedElements(new Object[] {});
		setPageComplete(detectPageComplete());
	}

	/**
	 * This method handles the modified event from the path combo box.
	 */
	protected void handlePathTextModifiedEvent() {
		setPageComplete(detectPageComplete());
	}

	/**
	 * Open the SaveAsDialog so the user can save the listing of selected breakpoints
	 */
	protected void handleDestinationBrowseButtonPressed() {
		FileDialog dialog = new FileDialog(getContainer().getShell(), SWT.SAVE | SWT.SHEET);
		dialog.setFilterExtensions(new String[]{"*."+IImportExportConstants.EXTENSION});  //$NON-NLS-1$
		dialog.setText(ImportExportMessages.WizardExportBreakpoints_0);
		String file = dialog.open();
		if(file != null) {
			IPath path = new Path(file);
			if (path != null) {
				setErrorMessage(null);
				if(path.getFileExtension() == null) {
					path = path.addFileExtension(IImportExportConstants.EXTENSION);
				}
				else if(!path.getFileExtension().equals(IImportExportConstants.EXTENSION)) {
					path = path.addFileExtension(IImportExportConstants.EXTENSION);
				}
				fDestinationNameField.setText(path.toString());
			}
		}
	}

	@Override
	public void createControl(Composite parent) {
		initializeDialogUnits(parent);
		Composite composite = SWTFactory.createComposite(parent, 1, 1, GridData.FILL_BOTH);
		SWTFactory.createLabel(composite, ImportExportMessages.WizardExportBreakpointsPage_2, 1);
		fTView = new EmbeddedBreakpointsViewer(composite, DebugPlugin.getDefault().getBreakpointManager(), fSelection);
		fTView.getViewer().addCheckStateListener(new ICheckStateListener() {
			@Override
			public void checkStateChanged(CheckStateChangedEvent event) {
				setPageComplete(detectPageComplete());
			}
		});
		fTView.getViewer().setSelection(fSelection);
		//ensure we can see the beginning check-boxes etc. (bug 180971)
		//this will not work in Windows Vista as there is no way to over-ride the default viewer item showing policy
		//by setting the horizontal bar selection index. I.e. the following line of code is ignored in Vista
		fTView.getViewer().getTree().getHorizontalBar().setSelection(0);
		createButtonsGroup(composite);
		createDestinationGroup(composite);
		fOverwriteExistingFilesCheckbox = SWTFactory.createCheckButton(composite, ImportExportMessages.WizardBreakpointsPage_6, null, false, 1);
		setControl(composite);
		setPageComplete(false);
		setMessage(ImportExportMessages.WizardBreakpointsPage_4);
		restoreWidgetState();
		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IDebugHelpContextIds.EXPORT_BREAKPOINTS_WIZARD_PAGE);

		Dialog.applyDialogFont(parent);
	}

	@Override
	public Image getImage() {
		return DebugUITools.getImage(IInternalDebugUIConstants.IMG_WIZBAN_EXPORT_BREAKPOINTS);
	}

	/**
	 * Creates the buttons for selecting all or none of the elements.
	 *
	 * @param parent the parent control
	 */
	private void createButtonsGroup(Composite parent) {
		Composite composite = SWTFactory.createComposite(parent, parent.getFont(), 3, 1, GridData.FILL_HORIZONTAL, 0, 0);
		fSelectAll = SWTFactory.createPushButton(composite, ImportExportMessages.WizardBreakpointsPage_1, null);
		fSelectAll.addListener(SWT.Selection, this);
		fDeselectAll = SWTFactory.createPushButton(composite, ImportExportMessages.WizardBreakpointsPage_2, null);
		fDeselectAll.addListener(SWT.Selection, this);
	}

	/**
	 * This method is used to determine if the page can be "finished".
	 *
	 * To be determined "finishable" there must be a save path and there must be
	 * a selection in the tree.
	 *
	 * @return if the prerequisites of the wizard are met to allow the wizard to complete.
	 */
	private boolean detectPageComplete() {
		String filepath = fDestinationNameField.getText().trim();
		if (filepath.equals(IInternalDebugCoreConstants.EMPTY_STRING)) {
			setErrorMessage(ImportExportMessages.WizardExportBreakpointsPage_0);
			return false;
		}
		IPath path = new Path(filepath);
		if(!path.removeLastSegments(1).toFile().exists()) {
			setErrorMessage(ImportExportMessages.WizardExportBreakpointsPage_3);
			return false;
		}
		int size = fTView.getCheckedElements().size();
		if (size == 0) {
			setErrorMessage(ImportExportMessages.WizardExportBreakpointsPage_1);
			return false;
		}
		setErrorMessage(null);
		setMessage(ImportExportMessages.WizardBreakpointsPage_4);
		return true;
	}

	/**
	 * Create the export destination specification widgets
	 *
	 * @param parent org.eclipse.swt.widgets.Composite
	 */
	protected void createDestinationGroup(Composite parent) {
		// destination specification group
		Composite comp = SWTFactory.createComposite(parent, parent.getFont(), 3, 1, GridData.FILL_HORIZONTAL, 0, 10);
		SWTFactory.createLabel(comp, ImportExportMessages.WizardBreakpointsPage_7, 1);

		fDestinationNameField = SWTFactory.createText(comp, SWT.SINGLE | SWT.BORDER, 1, GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
		fDestinationNameField.addListener(SWT.Modify, this);
		fDestinationBrowseButton = SWTFactory.createPushButton(comp, ImportExportMessages.WizardBreakpointsPage_8, null);
		fDestinationBrowseButton.addListener(SWT.Selection, this);
	}

	/**
	 * Save the state of the widgets select, for successive invocations of the wizard
	 */
	private void saveWidgetState() {
		IDialogSettings settings = getDialogSettings();
		if(settings != null) {
			settings.put(OVERWRITE_ALL_STATE, fOverwriteExistingFilesCheckbox.getSelection());
			settings.put(DESTINATION_FILE_NAME, fDestinationNameField.getText().trim());
		}
	}

	/**
	 * Restores the state of the wizard from previous invocations
	 */
	private void restoreWidgetState() {
		IDialogSettings settings = getDialogSettings();
		if(settings != null) {
			fOverwriteExistingFilesCheckbox.setSelection(Boolean.valueOf(settings.get(OVERWRITE_ALL_STATE)).booleanValue());
			String filename = settings.get(DESTINATION_FILE_NAME);
			if (filename != null) {
				fDestinationNameField.setText(filename);
			}
		}
	}

	/**
	 * The Finish button is clicked on the main wizard
	 * dialog to export the breakpoints, we write them out with all persistent
	 * information to a simple XML file via the use of XMLMemento.
	 *
	 * @return if the save operation was successful or not
	 */
	public boolean finish() {
		try {
			IPath path = new Path(fDestinationNameField.getText().trim());
			if(path.getFileExtension() == null) {
				path = path.addFileExtension(IImportExportConstants.EXTENSION);
			}
			else if(!path.getFileExtension().equals(IImportExportConstants.EXTENSION)) {
				path = path.addFileExtension(IImportExportConstants.EXTENSION);
			}
			saveWidgetState();
			if(path.toFile().exists() && !fOverwriteExistingFilesCheckbox.getSelection()) {
				if (!MessageDialog.openQuestion(null, ImportExportMessages.WizardBreakpointsPage_12, MessageFormat.format(ImportExportMessages.ImportExportOperations_0, new Object[] { path.toPortableString() }))) {
					return false;
				}
			}
			// collect breakpoints
			Object[] elements = fTView.getCheckedElements().toArray();
			List<IBreakpoint> breakpoints = new ArrayList<>();
			for (Object object : elements) {
				if (object instanceof IBreakpoint) {
					breakpoints.add((IBreakpoint) object);
				}
			}
			getContainer().run(false,
					true,
					new ExportBreakpointsOperation(
							breakpoints.toArray(new IBreakpoint[breakpoints.size()]),
							path.toOSString()));
		}
		catch (InterruptedException e) {
			DebugPlugin.log(e);
			return false;
		}
		catch (InvocationTargetException e) {
			DebugPlugin.log(e);
			return false;
		}
		return true;
	}
}
