/*
 * Copyright (C) 2008-2011, Google Inc.
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.lib;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/** ProgressMonitor that batches update events. */
public abstract class BatchingProgressMonitor implements ProgressMonitor {
	private long delayStartTime;

	private TimeUnit delayStartUnit = TimeUnit.MILLISECONDS;

	private Task task;

	/**
	 * Set an optional delay before the first output.
	 *
	 * @param time
	 *            how long to wait before output. If 0 output begins on the
	 *            first {@link #update(int)} call.
	 * @param unit
	 *            time unit of {@code time}.
	 */
	public void setDelayStart(long time, TimeUnit unit) {
		delayStartTime = time;
		delayStartUnit = unit;
	}

	public void start(int totalTasks) {
		// Ignore the number of tasks.
	}

	public void beginTask(String title, int work) {
		endTask();
		task = new Task(title, work);
		if (delayStartTime != 0)
			task.delay(delayStartTime, delayStartUnit);
	}

	public void update(int completed) {
		if (task != null)
			task.update(this, completed);
	}

	public void endTask() {
		if (task != null) {
			task.end(this);
			task = null;
		}
	}

	public boolean isCancelled() {
		return false;
	}

	/**
	 * Update the progress monitor if the total work isn't known,
	 *
	 * @param taskName
	 *            name of the task.
	 * @param workCurr
	 *            number of units already completed.
	 */
	protected abstract void onUpdate(String taskName, int workCurr);

	/**
	 * Finish the progress monitor when the total wasn't known in advance.
	 *
	 * @param taskName
	 *            name of the task.
	 * @param workCurr
	 *            total number of units processed.
	 */
	protected abstract void onEndTask(String taskName, int workCurr);

	/**
	 * Update the progress monitor when the total is known in advance.
	 *
	 * @param taskName
	 *            name of the task.
	 * @param workCurr
	 *            number of units already completed.
	 * @param workTotal
	 *            estimated number of units to process.
	 * @param percentDone
	 *            {@code workCurr * 100 / workTotal}.
	 */
	protected abstract void onUpdate(String taskName, int workCurr,
			int workTotal, int percentDone);

	/**
	 * Finish the progress monitor when the total is known in advance.
	 *
	 * @param taskName
	 *            name of the task.
	 * @param workCurr
	 *            total number of units processed.
	 * @param workTotal
	 *            estimated number of units to process.
	 * @param percentDone
	 *            {@code workCurr * 100 / workTotal}.
	 */
	protected abstract void onEndTask(String taskName, int workCurr,
			int workTotal, int percentDone);

	private static class Task implements Runnable {
		/** Title of the current task. */
		private final String taskName;

		/** Number of work units, or {@link ProgressMonitor#UNKNOWN}. */
		private final int totalWork;

		/** True when timer expires and output should occur on next update. */
		private volatile boolean display;

		/** Scheduled timer, supporting cancellation if task ends early. */
		private Future<?> timerFuture;

		/** True if the task has displayed anything. */
		private boolean output;

		/** Number of work units already completed. */
		private int lastWork;

		/** Percentage of {@link #totalWork} that is done. */
		private int lastPercent;

		Task(String taskName, int totalWork) {
			this.taskName = taskName;
			this.totalWork = totalWork;
			this.display = true;
		}

		void delay(long time, TimeUnit unit) {
			display = false;
			timerFuture = WorkQueue.getExecutor().schedule(this, time, unit);
		}

		public void run() {
			display = true;
		}

		void update(BatchingProgressMonitor pm, int completed) {
			lastWork += completed;

			if (totalWork == UNKNOWN) {
				// Only display once per second, as the alarm fires.
				if (display) {
					pm.onUpdate(taskName, lastWork);
					output = true;
					restartTimer();
				}
			} else {
				// Display once per second or when 1% is done.
				int currPercent = lastWork * 100 / totalWork;
				if (display) {
					pm.onUpdate(taskName, lastWork, totalWork, currPercent);
					output = true;
					restartTimer();
					lastPercent = currPercent;
				} else if (currPercent != lastPercent) {
					pm.onUpdate(taskName, lastWork, totalWork, currPercent);
					output = true;
					lastPercent = currPercent;
				}
			}
		}

		private void restartTimer() {
			display = false;
			timerFuture = WorkQueue.getExecutor().schedule(this, 1,
					TimeUnit.SECONDS);
		}

		void end(BatchingProgressMonitor pm) {
			if (output) {
				if (totalWork == UNKNOWN) {
					pm.onEndTask(taskName, lastWork);
				} else {
					int pDone = lastWork * 100 / totalWork;
					pm.onEndTask(taskName, lastWork, totalWork, pDone);
				}
			}
			if (timerFuture != null)
				timerFuture.cancel(false /* no interrupt */);
		}
	}
}
