package protocolP2P;
import protocolP2P.Payload;
import tools.HostItem;
import tools.BytesArrayTools;
import localException.SizeError;
import localException.InternalError;
import localException.TransmissionError;
import localException.ProtocolError;

/** Representation of payload for update ratio.
 * @author	Louis Royer
 * @author	Flavien Haas
 * @author	JS Auge
 * @version	1.0
 */
public class UpdateRatio extends Payload {
	private HostItem client;
	private HostItem server;
	private long dataSize;
	private static final int DATA_SIZE_POSITION = PAYLOAD_START_POSITION;
	private static final int SERVER_PORT_START_POSITION = DATA_SIZE_POSITION + 8;
	private static final int CLIENT_PORT_START_POSITION = SERVER_PORT_START_POSITION + 2;
	private static final int HOSTNAMES_START_POSITION = CLIENT_PORT_START_POSITION + 2;

	/** Constructor with hostItem (typically used by client)
	 * @param client	HostItem of the client application.
	 * @param server	HostItem of the server application.
	 * @param dataSize	size of data sent.
	 * @throws	InternalError
	 */
	public UpdateRatio(HostItem client, HostItem server, long dataSize) throws InternalError {
		super(RequestResponseCode.UPDATE_RATIO);
		this.client = client;
		this.server = server;
		this.dataSize = dataSize;
	}
	
	/** Constructor (typically used by tracker) with a byte[] parameter containing the Packet received.
	 * @param packet	the full Packet received
	 * @throws	SizeError
	 * @throws	InternalError
	 * @throws	ProtocolError
	 * @throws	TransmissionError
	 */
	protected UpdateRatio(byte[] packet) throws SizeError, ProtocolError, InternalError, TransmissionError {
		super(packet);
		int size = getPayloadSize(packet);
		dataSize = BytesArrayTools.readLong(packet, DATA_SIZE_POSITION);
		int portServer = BytesArrayTools.readInt16Bits(packet, SERVER_PORT_START_POSITION);
		int portClient = BytesArrayTools.readInt16Bits(packet, CLIENT_PORT_START_POSITION);
		String[] hostnames = BytesArrayTools.readStringArray(packet, HOSTNAMES_START_POSITION, size - HOSTNAMES_START_POSITION + PAYLOAD_START_POSITION, "\n");
		server = new HostItem(hostnames[0], portServer);
		client = new HostItem(hostnames[1], portClient);
	}

	/** Returns a byte[] containing Packet with padding.
	 * This Packet is still incomplete and should not be send directly.
	 * ProtocolP2PPacket will use this method to generate the complete Packet.
	 * @return Packet with padding
	 * @throws	InternalError
	 */
	protected byte[] toPacket() throws InternalError {
		String[] hostnames = { server.getHostname(), client.getHostname()};
		// compute total size
		int size = HOSTNAMES_START_POSITION + BytesArrayTools.computeStringArraySize(hostnames, "\n");
		byte[] packet = new byte[size]; // java initialize all to zero
		// set request/response code
		packet[RequestResponseCode.RRCODE_POSITION] = requestResponseCode.codeValue;
		// set Payload size
		setPayloadSize(size - PAYLOAD_START_POSITION, packet);
		// write dataSize
		BytesArrayTools.write(packet, DATA_SIZE_POSITION, dataSize);
		// write server port to Packet
		try {
			BytesArrayTools.write16Bits(packet, SERVER_PORT_START_POSITION, server.getPort());
		} catch (SizeError e) {
			throw new InternalError();
		}
		// write client port to Packet
		try {
			BytesArrayTools.write16Bits(packet, CLIENT_PORT_START_POSITION, client.getPort());
		} catch (SizeError e) {
			throw new InternalError();
		}
		// write hostnames to Packet
		BytesArrayTools.write(packet, hostnames, HOSTNAMES_START_POSITION, "\n");
		return packet;
	}

	/** Client getter.
	 * @return	client
	 */
	public HostItem getClient() {
		return client;
	}

	/** Server getter
	 * @return	server
	 */
	public HostItem getServer() {
		return server;
	}

	/** dataSize getter.
	 * @return	dataSize
	 */
	public long getDataSize() {
		return dataSize;
	} 


}
