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

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.swt.widgets.Display;

import com.patrikdufresne.managers.ManagerException;
import com.patrikdufresne.util.Localized;
import com.planimod.core.GeneratePlanifContext;
import com.planimod.ui.PlanimodPolicy;
import com.planimod.ui.MessageUtils;
import com.planimod.ui.theme.Resources;

/**
 * This action is used to create tasks for the current planif context without
 * computing the planif. This is useful to lock employee before generating the
 * planif.
 * 
 * @author Patrik Dufresne
 * 
 */
public class CreateTasksAction extends Action {

	/**
	 * The runnable context to display the action progress.
	 */
	private IRunnableContext context;

	/**
	 * Listen to dirty field
	 */
	private PropertyChangeListener listener = new PropertyChangeListener() {
		@Override
		public void propertyChange(PropertyChangeEvent evt) {
			if (GeneratePlanifContext.DIRTY.equals(evt.getPropertyName())) {
				setEnabled(canRun());
			}
		}
	};

	/**
	 * Used for localization.
	 */
	Localized localized = Localized.load(CreateTasksAction.class);

	/**
	 * The context used to generate a planif.
	 */
	GeneratePlanifContext planifContext;

	/**
	 * The shell provider to display message dialog.
	 */
	private IShellProvider shell;

	/**
	 * Create a new action.
	 * 
	 * @param context
	 */
	public CreateTasksAction(GeneratePlanifContext planifContext,
			IShellProvider shell, IRunnableContext context) {
		super();
		if (planifContext == null) {
			throw new NullPointerException("planifContext"); //$NON-NLS-1$
		}
		if (context == null || shell == null) {
			throw new NullPointerException();
		}
		this.shell = shell;
		this.planifContext = planifContext;
		this.planifContext.addPropertyChangeListener(this.listener);

		this.context = context;

		setText(this.localized.get("CreateTasksAction.text")); //$NON-NLS-1$
		setToolTipText(this.localized.get("CreateTasksAction.tooltipText")); //$NON-NLS-1$
		setImageDescriptor(Resources
				.getImageDescriptor(Resources.ICON_CREATE_TASKS_16));
		setEnabled(canRun());
	}

	/**
	 * Returns True if the action can be run.
	 * 
	 * @return
	 */
	protected boolean canRun() {
		return this.planifContext != null && this.planifContext.isDirty();
	}

	/**
	 * Should be called to dispose this action
	 */
	public void dispose() {
		if (this.planifContext != null) {
			this.planifContext.removePropertyChangeListener(this.listener);
		}
		this.context = null;
		this.listener = null;
		this.localized = null;
		this.planifContext = null;
		this.shell = null;
	}

	/**
	 * Return the current generate planif context for this action.
	 * 
	 * @return
	 */
	public GeneratePlanifContext getGeneratePlanifContext() {
		return this.planifContext;
	}

	/**
	 * Display an error message for the given exception.
	 * 
	 * @param e
	 */
	protected void handleManagerException(ManagerException e) {
		String message = this.localized
				.get("GeneratePlanifAction.generatePlanifError"); //$NON-NLS-1$
		String shotrDetail = this.localized
				.get("GeneratePlanifAction.exception.unknownReason"); //$NON-NLS-1$
		MessageUtils
				.openWarning(this.shell.getShell(), message, shotrDetail, e);
	}

	/**
	 * This implementation run the creation of the task.
	 */
	@Override
	public void run() {
		if (this.context == null) {
			return;
		}

		try {
			this.context.run(true, true, new IRunnableWithProgress() {
				@Override
				public void run(IProgressMonitor monitor)
						throws InvocationTargetException, InterruptedException {
					// Start the task
					monitor.beginTask(CreateTasksAction.this.localized
							.get("CreateTasksAction.beginTask"), //$NON-NLS-1$
							IProgressMonitor.UNKNOWN);
					try {
						CreateTasksAction.this.planifContext.createTasks();
					} catch (final ManagerException e) {
						Display.getDefault().asyncExec(new Runnable() {
							@Override
							public void run() {
								handleManagerException(e);
							}
						});
					}
					monitor.done();
				}
			});
		} catch (InvocationTargetException e) {
			PlanimodPolicy.showException(e);
		} catch (InterruptedException e) {
			PlanimodPolicy.showException(e);
		}
	}

}
