package mapping.data;

import java.io.Serializable;

/**
 * This class is an configuration message sent to servers (Puller objects) to
 * configure them.
 * 
 * @author Majd Kokaly
 * 
 */
public class MessageToServer implements Cloneable, Serializable {

	/**
	 * The serialVersionUID is used to universally identify this version of this
	 * class.
	 */
	private static final long serialVersionUID = -7990975011702029071L;

	/**
	 * Representing method 1 in availability prediction. Please refer to Section
	 * Availability model in the thesis document.
	 */
	public final static int WEIGHTED_MODE = 0;

	/**
	 * Representing method 2 in availability prediction. Please refer to Section
	 * Availability model in the thesis document.
	 */
	public final static int RECURSIVE_MODE = 1;

	/**
	 * Representing the use of neither availability prediction methods. Please
	 * refer to Section Availability Model in the thesis document.
	 */
	public final static int NON_ACTIVE_MODE = 2;

	/**
	 * The aj value. Please refer to Section Availability Model in the thesis
	 * document.
	 */
	double availability;
	
	/**
	 * The period for which aj is in effect. 
	 */
	double forHowLong;
	
	/**
	 * What availability Mode to use. WEIGHTED_MODE, RECURSIVE_MODE or NON_ACTIVE_MODE.
	 */
	int availabilityMode;
	
	/**
	 * Array of weights for mode WEIGHTED_MODE.
	 */
	double[] weights;
	
	/**
	 * N. Please refer to Section Availability Model in the thesis
	 * document.
	 */
	int N;
	
	/**
	 * c. Please refer to Section Availability Model in the thesis
	 * document.
	 */
	double c;

	public double getAvailability() {
		return availability;
	}

	public void setAvailability(double availability) {
		this.availability = availability;
	}

	public double getForHowLong() {
		return forHowLong;
	}

	public void setForHowLong(double forHowLong) {
		this.forHowLong = forHowLong;
	}

	public int getAvailabilityMode() {
		return availabilityMode;
	}

	public void setAvailabilityMode(int availabilityMode) {
		this.availabilityMode = availabilityMode;
	}

	public double[] getWeights() {
		return weights;
	}

	public void setWeights(double[] weights) {
		this.weights = weights;
	}

	public int getN() {
		return N;
	}

	public void setN(int n) {
		N = n;
	}

	public double getC() {
		return c;
	}

	public void setC(double c) {
		this.c = c;
	}

	public MessageToServer() {
		this.availability = 1.0;
		this.forHowLong = 32000;
		this.availabilityMode = WEIGHTED_MODE;
		double[] a = { 0.4, 0.3, 0.2, 0.1 };
		this.weights = a;
		N = 4;
		this.c = 0.5;
	}

	public MessageToServer(double percentage, double forHowLong, int availabilityMode, double[] weights, int n, int c) {
		this.availability = percentage;
		this.forHowLong = forHowLong;
		this.availabilityMode = availabilityMode;
		this.weights = weights;
		this.N = n;
		this.c = c;
	}

	public Object clone() {
		try {
			return super.clone();
		} catch (CloneNotSupportedException e) {
			return null;
		}
	}
	
	/**
	 * returns the message to be sent to servers.
	 * The format is: #percentage#forHowLong#AvailabilityManagerMode#N#Weights#C
	 */
	public String toString() {
		String availabilityModeString;
		if (this.availabilityMode == WEIGHTED_MODE)
			availabilityModeString = "weighted";
		else if (this.availabilityMode == RECURSIVE_MODE)
			availabilityModeString = "recursive";
		else
			// if (this.availabilityMode == 2)
			availabilityModeString = "non-active";

		StringBuffer weightsString = new StringBuffer(new String("-1"));
		if (this.weights != null) {
			weightsString = new StringBuffer(50);
			for (int i = 0; i < this.weights.length; i++) {
				weightsString.append(this.weights[i]);
				if (i + 1 < this.weights.length)
					weightsString.append(';');
			}
		}
		// #percentage#forHowLong#AvailabilityManagerMode#N#Weights#C
		return this.availability + "#" + this.forHowLong + "#" + availabilityModeString + "#" + this.N + "#"
				+ weightsString.toString() + "#" + this.c;

	}
}
