package org.kne.cloud.network.klalb;

import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;

import org.kne.cloud.network.NetworkPacket;

public class DATATPacket extends KLALBPacket implements PortPacket{
	/*private int sport,dport;
	private long number;
	private int size; 
	private byte[]data;
	private int sendcount;*/
	private static final int HEADER_LENGTH=20;

	@Override
	public long getTotalLength() {
		return HEADER_LENGTH+dataBuffer.limit();
	}
	
	private ByteBuffer dataBuffer;//=NetworkPacket.databufferpool_65535.borrow();
	
	public DATATPacket(int sport,int dport,long number,int mtulimit) {
		super(DATAT,HEADER_LENGTH);
		/*this.sport=sport;
		this.dport=dport;
		this.number=number;
		this.data=data;
		this.size=size;*/
		klalbHeader.putInt(sport);
		klalbHeader.putInt(dport);
		klalbHeader.putLong(number);
		numberc=number;
		klalbHeader.put((byte) 0);
		klalbHeader.putChar((char) 0);
		
		//dataBuffer.limit(mtulimit);
		dataBuffer=NetworkPacket.bufferAllocator.allocate(mtulimit);
	}

	public int getSendcount() {
		return klalbHeader.get(17);
	}

	public DATATPacket() {
		super(DATAT,HEADER_LENGTH);
	}

	public DATATPacket(ByteBuffer bb) {
		super(bb,HEADER_LENGTH);
	}

	public int getSrcPort() {
		return klalbHeader.getInt(1);
	}

	public int getDstPort() {
		return klalbHeader.getInt(5);
	}

	private long numberc=Long.MIN_VALUE;
	public long resendtimer;
	public long getNumber() {
		if(numberc!=Long.MIN_VALUE) {
			return numberc;
		}
		return (numberc= klalbHeader.getLong(9));
	}
	public ByteBuffer getDataBuffer() {
		return dataBuffer;
	}

	@Override
	public String toString() {
		byte[]b=new byte[Math.min(dataBuffer.limit(),10)];
		dataBuffer.get(0, b);
		return "DATAT "+getSrcPort()+"->"+getDstPort()+" "+getNumber()+"["+getSize()+"] "+Arrays.toString(b);
	}
	
	@Override
	public int hashCode() {
		return (int) getNumber();
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == null)
			return false;
		try {
		DATATPacket other = (DATATPacket) obj;
		return getNumber() == other.getNumber();
		}catch(ClassCastException e) {
			return false;
		}
	}

	public int getSize() {
		return dataBuffer.limit();
	}
	private int sendCounter=0;

	public int getSendCounter() {
		return sendCounter;
	}
	
	public void incSendCounter() {
		sendCounter++;
	}
	
	@Override
	public void writeToChannel(WritableByteChannel dto) throws IOException {
		klalbHeader.put(17, (byte) getSendCounter());
		klalbHeader.putChar(18, (char) dataBuffer.limit());
		super.writeToChannel(dto);
		//System.out.println(dataBuffer);
		dto.write(dataBuffer.slice(0, dataBuffer.limit()));
	}

	@Override
	public void readFromChannel(ReadableByteChannel din) throws IOException {
		super.readFromChannel(din);
		numberc=Long.MIN_VALUE;
		int limit=klalbHeader.getChar(18);
		//dataBuffer.clear();
		//dataBuffer.limit();
		dataBuffer=NetworkPacket.bufferAllocator.allocate(limit);
		 while(dataBuffer.hasRemaining()){
			if(din.read(dataBuffer)==-1) {
				throw new EOFException();
			}
		}
		 dataBuffer.flip();
	}
	
	
}
