/* ======================================================================
   Parts Copyright 2006 University of Leeds, Oxford University, University of the Highlands and Islands.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

====================================================================== */

package org.bodington.server.userimport;
import java.util.Calendar;
import java.util.Properties;
import java.util.Date;
import org.apache.log4j.Logger;

import org.bodington.server.JobSession;


/** Main controller class that is in control of the general import execution.
It ensures that only a single import process is running at any time.
<p>
<br/>$HeadURL: https://svn.oucs.ox.ac.uk/sysdev/src/u/usrgrpgen/tags/2.0-3/uk/ac/ox/usrgrpgen/ImportManager.java $
<br/>$LastChangedRevision: 3381 $
<br/>$LastChangedDate: 2004-04-02 16:43:20 +0100 (Fri, 02 Apr 2004) $
<br/>$LastChangedBy: mats $
</p>
@author	Mats Henrikson
@version $LastChangedRevision: 3381 $
*/
public class ImportManager {


	/** The properties file to get properties from. */
	private static UserGroupImporter importer;
	/** Record when the import was started.	 */
	private static Calendar started;
	/** The Logger instance to use. */
	private static final Logger log = Logger.getLogger(ImportManager.class);
	
	
	/** The import has been run before but is currently stopped. */
	public static final int STOPPED = 0;
	/** The import is currently running. */
	public static final int RUNNING = 1;
	/** The import is still running but has been flagged to shutdown */
	public static final int SHUTDOWN = 2;
	/** The import has not yet been setup */
	public static final int SETUP = 3;


	/** Initialises a new import manager with a certain Properties object.
	Whenever this is called any old import manager will be killed and thrown
	away.
	@param	props	The properties instance to use.
	@throws	AlreadyRunningException	Throws an ARE if there is already an
			import in progress, it is up to the caller to decide if that
			instance should be killed or not.
	*/
	public synchronized static void init(Properties props)
			throws AlreadyRunningException, ConfigurationException {
		if(importer != null && importer.isRunning()) {
			throw new AlreadyRunningException();
		}
		importer = new UserGroupImporter(props);
		log.info("Initialised a new UserGroupImporter instance.");
	}


	/** Starts the importer thread. NOTE: it may take a little while for the
	thread to actually start after calling this method, so it may be an idea to
	sleep for a second or so before checking the status.
	@throws	AlreadyRunningException	Throws an ARE if there is already an
			import in progress, it is up to the caller to decide if that
			instance should be killed or not.
	@throws	NotInitialisedException Throws a NIE if it hasn't been initialised
			with an importer yet.
	*/
	public synchronized static void start()
			throws AlreadyRunningException, NotInitialisedException {
		if(importer == null) { throw new NotInitialisedException(); }
		else if(importer.isRunning()) { throw new AlreadyRunningException(); }
		Thread t = new Thread(importer);
		t.start();
		started = Calendar.getInstance();
		log.info("Started importing new users and groups.");
	}


	/** Stop a currently running import dead in it's tracks*. Note that this
	method may return before the import has actually stopped.
	<p>* Not strictly true, it will actually stop it nicely at the next
	convenient opportunity, but dieDieDie() is easier to remember than
	pleaseStopAtNextConvenientOpportunity().</p>
	*/
	public static void dieDieDie() {
		if(importer != null) { importer.dieDieDie(); }
	}


	/** Checks to see if there is an import in progress, returns false if
	there isn't an importer instance. */
	public synchronized static boolean isRunning() {
		if(importer == null) { return false; }
		return importer.isRunning();
	}
	
	
	/**
	 * Checks to see if we are currently in shutdown.
	 * @return True if the importer is still running but currently in shudown.
	 */
	public static boolean isInShutdown() {
		if (importer == null) { return false; }
		return importer.isInShutdown();
	}
	
	/**
	 * Return when the import was started.
	 * @return When the import was started, if no import has been run it will be null.
	 */
	public static Calendar getStarted() {
		return (Calendar)started.clone();
	}
	
	/**
	 * Checks to see what state the import is in.
	 * @return Current status of the import
	 */
	public static int getStatus() {
		if (isInitialised()) {
			if (isRunning()) {
				if (importer.isInShutdown()) {
					return SHUTDOWN;
				} else {
					return RUNNING;
				}
			} else {
				return STOPPED;
			}
		} else {
			return SETUP;
		}
	}
	
	/**
	 * Has the importer been setup.
	 * @return True if it is ok to start the import.
	 */
	public static  boolean isInitialised() {
		return importer == null;
	}
	

	/**
	 * Get the progress of the importer in terms of number of objects processed.
	 * @return An int array. [0] - users. [1] - groups. [2] - resources.
	 */
	public static int[] progress() {
		if (importer == null) 
			return  new int[] {0,0,0};
		return new int[] {
				importer.getProcessedUsers(),
				importer.getCreatedGroups(),
				importer.getCreatedResources()
		};
		
	}
	
	
	/** Returns a String saying what status the system is currently in, with any
	counts of users saved, groups created etc.
	@return	A String message giving the status of the system.
	*/
	public static String status() {
		StringBuffer status = new StringBuffer();
		try {
			if(importer == null) { status.append("Not initialised"); }
			else {
				status.append("Initialised");
				if(importer.isRunning()) { status.append(", running"); }
				else { status.append(", not running"); }
			}
			status.append(". (")
				.append(new Date())
				.append(")\n")
				.append("Users processed: ")
				.append(importer.getProcessedUsers())
				.append("\nGroups created: ")
				.append(importer.getCreatedGroups())
				.append("\nResources created: ")
				.append(importer.getCreatedResources());
		}
		catch(Exception e) {
			status.append(" Something bad happened, please try again. If it ")
				.append("keeps happening then you may have a problem. This ")
				.append("was the exception caught: ")
				.append(e.toString());
		}
		return status.toString();
	}
}
