package com.feeyo.net.udp.packet;

import java.util.ArrayList;
import java.util.List;
import java.util.zip.CRC32;

/**
 * 
 * @author zhuam
 *
 */
public class V5PacketEncoder {

	public List<V5Packet> encode(int mtu, int packetSender, byte packetType, byte[] packetReserved, int packetId, byte[] data) {
		
		//
		if ( mtu <= V5Packet.HEAD_LENGTH + V5Packet.TAIL_LENGTH ) {
			throw new java.lang.IllegalArgumentException(" mtu must be greater than packet header size , " 
						+ " headSize=" + V5Packet.HEAD_LENGTH + ", tailSize=" + V5Packet.TAIL_LENGTH );
		}
		
		//1、根据原始的包长和MTU值 来分成几个碎片包
		int maxLen = mtu - V5Packet.HEAD_LENGTH - V5Packet.TAIL_LENGTH;
		int n = data.length / maxLen;
		if ( (data.length % maxLen) != 0 )
			n++;
		
		//2、构造碎片包
		List<V5Packet> packs = new ArrayList<V5Packet>(n);
		for (int i = 0; i < n; i++) {

			int dataOffset =  i * maxLen;
			int dataLength = (i < (n - 1)) ? maxLen : data.length - i * maxLen;
			
			//
			byte[] packetData = new byte[ dataLength ];
			
			//
			int idx = 0;
			int start = dataOffset;
			int end = dataOffset + dataLength;
			for (int j = start; j < end; j++) {
				packetData[idx++] = data[j];
			}
			
			// 包尾,crc
			CRC32 crc32 = new CRC32();
			crc32.update( packetData, 0, packetData.length);
			long crc = crc32.getValue();
	
			int packetLength = data.length;
			int packetOffset =  i * maxLen;
			
			packs.add( new V5Packet(packetSender, packetType, packetReserved, packetId, packetLength, packetOffset, packetData, crc) );
		}
		
		return packs;
		
	}
	
	public byte[] encode(V5Packet packet) {
		
		int packetSender = packet.getPacketSender();
		byte packetType = packet.getPacketType();
		byte[] packetReserved = packet.getPacketReserved();
		int packetId = packet.getPacketId();
		int packetLength = packet.getPacketLength();
		int packetOffset = packet.getPacketOffset();
		byte[] packetData = packet.getPacketData();
		long crc = packet.getCrc();
		
		
		byte[] pdu = new byte[V5Packet.HEAD_LENGTH + packetData.length + V5Packet.TAIL_LENGTH];
		int idx = 0;
		
		
		pdu[idx++] = 89;
		pdu[idx++] = 89;
		
		// 发送方
		pdu[idx++] = ByteUtil.getByte3(packetSender);
		pdu[idx++] = ByteUtil.getByte2(packetSender);
		pdu[idx++] = ByteUtil.getByte1(packetSender);
		pdu[idx++] = ByteUtil.getByte0(packetSender);
		
		// 包类型
		pdu[idx++] = packetType;
		
		// 预留
		System.arraycopy(packetReserved, 0, pdu, idx, packetReserved.length);
		idx += 8;
		
		// 包唯一编号
		pdu[idx++] = ByteUtil.getByte3(packetId);
		pdu[idx++] = ByteUtil.getByte2(packetId);
		pdu[idx++] = ByteUtil.getByte1(packetId);
		pdu[idx++] = ByteUtil.getByte0(packetId);
		
		// 包长
		pdu[idx++] = ByteUtil.getByte3(packetLength);
		pdu[idx++] = ByteUtil.getByte2(packetLength);
		pdu[idx++] = ByteUtil.getByte1(packetLength);
		pdu[idx++] = ByteUtil.getByte0(packetLength);
		
		// 包偏移值
		pdu[idx++] = ByteUtil.getByte3(packetOffset);
		pdu[idx++] = ByteUtil.getByte2(packetOffset);
		pdu[idx++] = ByteUtil.getByte1(packetOffset);
		pdu[idx++] = ByteUtil.getByte0(packetOffset);
		
		
		idx = V5Packet.HEAD_LENGTH;
		
		for (int j = 0; j < packetData.length; j++) {
			pdu[idx++] = packetData[j];
		}
		
		// 包尾,crc		
		pdu[idx++] = ByteUtil.getByte7( crc );
		pdu[idx++] = ByteUtil.getByte6( crc );
		pdu[idx++] = ByteUtil.getByte5( crc );
		pdu[idx++] = ByteUtil.getByte4( crc );
		pdu[idx++] = ByteUtil.getByte3( crc );
		pdu[idx++] = ByteUtil.getByte2( crc );
		pdu[idx++] = ByteUtil.getByte1( crc );
		pdu[idx++] = ByteUtil.getByte0( crc );

		return pdu;
	}

}