/*
 * Copyright (c) 2011, Patrik Dufresne. All rights reserved.
 * Patrik Dufresne PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.planimod.ui.views.nonavailabilities;

import java.util.Arrays;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Shell;

import com.patrikdufresne.managers.ManagerException;
import com.patrikdufresne.util.Localized;
import com.planimod.core.NonAvailability;
import com.planimod.core.PlanimodManagers;
import com.planimod.core.TimeRanges;
import com.planimod.ui.PlanimodPolicy;
import com.planimod.ui.theme.Resources;

/**
 * Action to edit a non-availability event.
 * 
 * @author Patrik Dufresne
 * 
 */
public class EditNonAvailabilityAction extends Action {

	/**
	 * Property name of this action non-availability event (value
	 * <code>"nonAvailability"</code>). The non-availability property is used to
	 * define the object to edit.
	 */
	public static final String NON_AVAILABILITY = "nonAvailability"; //$NON-NLS-1$

	public static void edit(PlanimodManagers managers, Shell shell,
			NonAvailability event) {

		boolean isArchived = event.getEmployee().getArchivedDate() != null;

		// Open the dialog
		NonAvailabilityDialog dlg = new NonAvailabilityDialog(shell, managers,
				NonAvailabilityDialog.EDIT);
		dlg.setStartDate(event.getStartDate());
		dlg.setEndDate(event.getEndDate());
		dlg.setSummary(event.getSummary());
		dlg.setEmployee(event.getEmployee());
		dlg.setVisible(event.isVisible());
		if (dlg.open() != Window.OK) {
			// Cancel by user
			return;
		}

		// Don't change the employee if it was archived.
		if (!isArchived) {
			event.setEmployee(dlg.getEmployee());
		}
		event.setStartDate(TimeRanges.removeSecond(dlg.getStartDate()));
		event.setEndDate(TimeRanges.removeSecond(dlg.getEndDate()));
		event.setSummary(dlg.getSummary());
		event.setVisible(dlg.getVisible());

		// Save the event
		try {
			managers.getNonAvailabilityManager().update(Arrays.asList(event));
		} catch (ManagerException e) {
			PlanimodPolicy.showException(e);
			return;
		}
	}

	/**
	 * Managers to use
	 */
	private PlanimodManagers managers;

	/**
	 * The event to edit.
	 */
	private NonAvailability nonAvailability;

	/**
	 * Shell provider.
	 */
	private IShellProvider shellProvider;

	/**
	 * Create a new action.
	 * 
	 * @param managers
	 * @param provider
	 */
	public EditNonAvailabilityAction(PlanimodManagers managers,
			IShellProvider provider) {
		if (managers == null || provider == null) {
			throw new NullPointerException();
		}
		this.managers = managers;
		this.shellProvider = provider;
		setText(Localized.get(EditNonAvailabilityAction.class,
				"EditNonAvailabilityAction.text")); //$NON-NLS-1$
		setToolTipText(Localized.get(EditNonAvailabilityAction.class,
				"EditNonAvailabilityAction.tooltipText")); //$NON-NLS-1$
		setImageDescriptor(Resources.getImageDescriptor(Resources.ICON_EDIT_16));
		setEnabled(canRun());

	}

	/**
	 * Check if this action can be run.
	 * 
	 * @return True if this action can be run.
	 */
	protected boolean canRun() {
		return this.nonAvailability != null;
	}

	/**
	 * Returns the current non-availability even.
	 * 
	 * @return
	 */
	public NonAvailability getNonAvailability() {
		return this.nonAvailability;
	}

	/**
	 * This implementation open a dialog to edit the non-availability.
	 */
	@Override
	public void run() {
		if (this.nonAvailability == null) {
			return;
		}
		edit(this.managers, this.shellProvider.getShell(), this.nonAvailability);
	}

	/**
	 * Sets the non-availability to edit.
	 * 
	 * @param nonAvailability
	 *            the non-availability or null
	 */
	public void setNonAvailability(NonAvailability nonAvailability) {
		if ((this.nonAvailability == null && nonAvailability != null)
				|| (this.nonAvailability != null && nonAvailability == null)
				|| (this.nonAvailability != null && nonAvailability != null && !nonAvailability
						.equals(this.nonAvailability))) {
			NonAvailability oldValue = this.nonAvailability;
			this.nonAvailability = nonAvailability;
			firePropertyChange(NON_AVAILABILITY, oldValue, this.nonAvailability);
			setEnabled(canRun());
		}
	}
}