/*
 * Created on 17-apr-2004
 *
 */
package convFramework.domain;

import convFramework.traffic.*;

/**
 * @author Lompa
 * Classe che rappresenta un pacchetto base per il framework; non ve istanzieta utilizzando il costruttore,
 * occorre invece usare l'apposita claffe factory (PacketFactory)
 * 
 * La classe packet può esssere estesa per modellare i vari pacchetti utilizzati dai protocolli. Per crearli
 * occorre definire una apposita factory o estendere quella base 
 */
public abstract class Packet {
	
	/* campi */
	private Node sender = null;
	private Node receiver = null;
	private IPacketID packetID = null;
	private IPacketID acknowledgedPacket = null;
	private IPacketID previousPacket = null;
	private IConversationID convID = null;
	private boolean ackRequired = false;
	private boolean useAutoAck = false;
	private boolean isAck = false;
	private boolean isSequence = false;
	
	/**
	 * Costruttore base, da non utilizzare (va usata la classe PacketFactory)
	 * @param packetID l'id del pacchetto
	 * @param convID l'id della conversazione di cui fa parte
	 */
	public Packet(IPacketID packetID, IConversationID convID){
		this.packetID = packetID;
		this.convID = convID;
	}
	
	/**
	 * Restituisce il mittente del pacchetto
	 * @return il nodo mittente
	 */
	public Node getSender(){ return this.sender; }
	
	/**
	 * Imposta il mittente del messaggio
	 * @param sender il nodo mittente
	 */
	public void setSender(Node sender){ this.sender = sender; }
	
	/**
	 * Restituisce il destinatario del pacchetto
	 * @return il nod destinatario
	 */
	public Node getReceiver(){ return this.receiver; }
	
	/**
	 * Imposta il destinatario del pacchetto
	 * @param servant il destinatario
	 */
	public void setReceiver(Node receiver){ this.receiver = receiver; }
	
	/**
	 * Restituisce l'identificatore del pacchetto
	 * @return l'identificatore del pacchetto
	 */
	public IPacketID getPacketID(){ return this.packetID; }
	
	/**
	 * Se il pacchetto è la risposta ad un altro, questo metodo consente di recuperarne
	 * l'identificatore
	 * @return l'identificatore del pacchetto di cui quello corrente è risposta
	 */
	public IPacketID getAcknowledgedPacket(){ return this.acknowledgedPacket; }
	
	/**
	 * Indica che questo pacchetto è risposta a quello il cui id viene specificato
	 * @param acknowledgedPacket l'id del pacchetto cui quello corrente risponde
	 */
	public void setAcknowledgedPacket(IPacketID referredPacket){ this.acknowledgedPacket = referredPacket; }
	
	
	/**
	 * Restituisce l'id della conversazione di cui quest paccheto fa parte
	 * @return l'id della conversazione
	 */
	public IConversationID getConversationID(){ return this.convID; }
	
	/**
	 * Restituisce un flag che indica se per questo pacchetto è richiesta un risposta o no
	 * @return il valore del flag
	 */
	public boolean isAckRequired(){ return this.ackRequired; }
	
	/**
	 * Specifica se per questo pacchetto è richiesta una risposta
	 * @param value il valore dell'opzione
	 */
	public void setAckRequired(boolean value){
		this.ackRequired = value;
		if (!value && this.useAutoAck) this.useAutoAck = false;
	}
	
	/**
	 * Permette di verificare se il pacchetto è un risposta ad un altro
	 * @return il valore dell'opzione
	 */
	public boolean isAck(){ return this.isAck; }
	
	/**
	 * Indica se il pacchetto è una risposta o no; se sis attiva l'opzione isAck l'opzione
	 * isSequence diventa automanticamente falsa
	 * @param value il valore dell'opzione
	 */
	public void setAck(boolean value){
		this.isAck = value;
	}
	
	/**
	 * Verifica se il pacchetto fa parte di una sequenza
	 * @return il valore dell'opzione
	 */
	public boolean isSequence(){ return this.isSequence; }
	
	/**
	 * Indica se il pacchetto fa parte di una sequenza; se si attiva l'opzione isSequence
	 * l'opzione isAck diventa falsa
	 * @param value il valore dell'opzione
	 */
	public void setSequence(boolean value){
		this.isSequence = value;
	}

	/**
	 * @return
	 */
	public String getType(){
		return getTypeDescription();
	}
	
	/**
	 * @return
	 */
	public static String getTypeDescription(){
		return "abstractPacket";
	}
	/**
	 * @return Returns the previousPacket.
	 */
	public IPacketID getPreviousPacket() {
		return previousPacket;
	}
	/**
	 * @param previousPacket The previousPacket to set.
	 */
	public void setPreviousPacket(IPacketID previousPacket) {
		this.previousPacket = previousPacket;
	}
	
	/**
	 * @param packet
	 */
	public void acknowledge(Packet packet){
		this.isAck = true;
		this.acknowledgedPacket = packet.getPacketID();
	}
	
	/**
	 * @param packet
	 */
	public void follows(Packet packet){
		this.isSequence = true;
		this.previousPacket = packet.getPacketID();
	}
	/**
	 * @return Returns the useAutoAck.
	 */
	public boolean isAutoAckRequired() {
		return useAutoAck;
	}
	/**
	 * Indica se utilizzare l'autoack; imposta atuomaticamente allo stesso valore anche "ackRequired"
	 * @param useAutoAck 
	 */
	public void setAutoAckRequired(boolean autoAck) {
		this.useAutoAck = autoAck;
		if (autoAck) this.ackRequired = true;
	}
}
