package mapping;

import mapping.data.Server;
import mapping.data.IDsQueue;

/**
 * 
 * This Thread is a helper thread for the LPAS_DG_MS objects. It is a thread
 * that iterates over the AvailableServers Queue and asks the LPAS_DG_MS object
 * to map a job for the server in the head of that queue. If the jobs queue has
 * no jobs that the current available server can execute, the next server in
 * line is considered.
 * 
 * @author Majd Kokaly
 * 
 */
public class LPAS_DG_MS_ThreadRB implements Runnable {

	/**
	 * This flag tells the thread if it is alive or should kill itself.
	 */
	private boolean alive = true;

	/**
	 * A Thread objects that runs this Runnable class.
	 */
	private Thread thisThread;

	/**
	 * The LPAS_DG_MS that this thread helps.
	 */
	LPAS_DG_MS lpas_dg_ms;

	/**
	 * Defualt constructor
	 * 
	 * @param lpas_dg_ms
	 *            To set the lpas_dg_ms data member.
	 */
	public LPAS_DG_MS_ThreadRB(LPAS_DG_MS lpas_dg_ms) {
		this.setAlive(true);
		this.setLpas_dg_ms(lpas_dg_ms);
	}

	public synchronized boolean isAlive() {
		return alive;
	}

	public synchronized void setAlive(boolean alive) {
		this.alive = alive;
	}

	public LPAS_DG_MS getLpas_dg_ms() {
		return lpas_dg_ms;
	}

	public void setLpas_dg_ms(LPAS_DG_MS lpas_dg_ms) {
		this.lpas_dg_ms = lpas_dg_ms;
	}

	/**
	 * This method starts the thread.
	 */
	public void startThread() {
		System.out.println("LPAS Thread started");
		thisThread = new Thread(this);
		thisThread.start();
	}

	/**
	 * This method stops the thread.
	 */
	public void stopThread() {
		this.setAlive(false);
		thisThread.interrupt();
		thisThread = null;
	}

	/**
	 * This loop is iterateD over the available queue and asks the LPAS_DG_MS to
	 * find a job for that server. If the jobs queue has no jobs that the
	 * current available server can execute, the next server in line is
	 * considered.
	 */
	public void run() {
		Server server = null;
		int serverID, result;
		long sleepTime = 0;
		IDsQueue<Integer> q = this.getLpas_dg_ms().getMapper().getAvailableServersQueue();
		while (this.isAlive()) {
			if (!q.isEmpty()) {
				serverID = q.peak();
				server = this.getLpas_dg_ms().getMapper().getServersTable().get(serverID);

				/*
				 * Any server in the available queue should satisfy this
				 * condition. Just to be sure that the server is not busy and
				 * nor down.
				 */
				if (server.getNumberOfActiveJobs() == 0
						&& !this.getLpas_dg_ms().getMapper().getServersTable().isServerDown(serverID)) {
					/*
					 * Possible values of result: ALL_QUEUES_ARE_EMPTY
					 * SUTIABLE_JOB_FOUND_BUT_COULD_NOT_BE_SENT
					 * NO_JOB_IN_QUEUE_IS_SUITABLE_FOR_SERVER FATAL_ERROR
					 * SUCCESS
					 * 
					 */
					result = this.getLpas_dg_ms().sendJobForServer(serverID);
					System.out.print("LPAS_THREAD: server " + serverID + " is sent.");
					switch (result) {
					case LPAS_DG_MS.ALL_QUEUES_ARE_EMPTY:
						sleepTime = 1000;
						System.out.println("Queues are empty.");
						break;
					case LPAS_DG_MS.NO_JOB_IN_QUEUE_IS_SUITABLE_FOR_SERVER:
						System.out.println("No suitable job.");
						q.advanceInRoundRobinFashion();
						sleepTime = 10;
						break;
					default:
						System.out.println("Success.");
						sleepTime = 200;
					}

					try {
						Thread.sleep(sleepTime);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

				}
			}
		}
	}
}
