package cz.vutbr.feec.packets.ttp;

import cz.vutbr.feec.packets.IPacket;
import cz.vutbr.feec.packets.PacketGenerateException;
import cz.vutbr.feec.packets.PacketParseException;
import cz.vutbr.feec.packets.PacketUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

public class GeneralTTPHeader implements IPacket {
	private int version;

//	private int padding;

	private int packetType;

	private long feedbackTreeId;

	private int length; 

	public GeneralTTPHeader(int packetType) {
		this.setPacketType(packetType);
	}
	
	public GeneralTTPHeader() {
		
	}

	public int generate(byte[] buffer, int offset)
			throws PacketGenerateException {
		assert PacketUtils.checkSize(version, 3);
		//assert PacketUtils.checkSize(padding, 1);				Padding was removed after group confirmation
		assert PacketUtils.checkSize(packetType, 5);
		assert PacketUtils.checkSize(feedbackTreeId, 16);
		assert PacketUtils.checkSize(length, 8);

		byte V_TreeId = (byte) ((version << 5) & 0xE0 | packetType & 0x1F);
		buffer[offset] = V_TreeId;

		PacketUtils.setOctet2(buffer, offset + 1, this.getFeedbackTreeId());
		PacketUtils.setOctet1(buffer, offset + 3, this.getLength());

		// hlavicka zabere celkem 32 bitu
		return 4;
	}

	public int parse(byte[] resultArray, int startPos, int length)
			throws PacketParseException {
		if (length < 4) {
			throw new PacketParseException("Header is too short");
		}
		int first = PacketUtils.getOctet1(resultArray, startPos);
		this.setVersion((first & 0xE0) >> 5);
		//this.setPadding((first & 0x10) >> 4);					Padding was removed after group confirmation
		this.setPacketType(first & 0x1F);
		this.setFeedbackTreeId(PacketUtils.getOctet2(resultArray, 1));
		this.setLength(PacketUtils.getOctet1(resultArray, 3));
		return 4;
	}

	public int getVersion() {
		return this.version;
	}

	public void setVersion(int version) {
		this.version = version;
	}

	/*public int getPadding() {
		return this.padding;
	}

	public void setPadding(int padding) {
		this.padding = padding;
	}*/

	public int getPacketType() {
		return this.packetType;
	}

	public void setPacketType(int packetType) {
		this.packetType = packetType;
	}

	public long getFeedbackTreeId() {
		return this.feedbackTreeId;
	}

	public void setFeedbackTreeId(long feedbackTreeId) {
		this.feedbackTreeId = feedbackTreeId;
	}

	public int getLength() {
		return this.length;
	}

	public void setLength(int length) {
		this.length = length;
	}

	/**
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return new ToStringBuilder(this).append("version", this.version)
				.append("packetType",
						this.packetType).append("length", this.length).append(
						"feedbackTreeId", this.feedbackTreeId).toString();
	}

	/**
	 * @see java.lang.Comparable#compareTo(Object)
	 */
	public int compareTo(Object object) {
		GeneralTTPHeader myClass = (GeneralTTPHeader) object;
		return new CompareToBuilder().append(this.packetType,
				myClass.packetType).append(this.length, myClass.length).append(this.feedbackTreeId,
				myClass.feedbackTreeId).append(this.version, myClass.version)
				.toComparison();
	}

	/**
	 * @see java.lang.Object#equals(Object)
	 */
	@Override
	public boolean equals(Object object) {
		if (!(object instanceof GeneralTTPHeader)) {
			return false;
		}
		GeneralTTPHeader rhs = (GeneralTTPHeader) object;
		return new EqualsBuilder().append(
				this.packetType, rhs.packetType)
				.append(this.length, rhs.length).append(this.feedbackTreeId,
						rhs.feedbackTreeId).append(this.version, rhs.version)
				.isEquals();
	}

	/**
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return new HashCodeBuilder(-2024644299, 591823357).append(this.packetType).append(this.length)
				.append(this.feedbackTreeId).append(
						this.version).toHashCode();
	}
	
}
