package common;

import java.io.IOException;
import java.net.ProtocolException;

import org.xbill.DNS.Name;

public class ClientPacket extends Packet {
		
	public ClientPacket(short clientID, byte packetID, byte flags, byte encBase, byte lastPidSeen, byte checksum, byte[] dataContent) {
		super(clientID, packetID, flags, encBase, lastPidSeen, checksum, dataContent);
	}
	
	/*public ClientPacket(Name name) throws ProtocolException {
		super();
		decodePacket(name);
	}*/
	
	public ClientPacket(byte[] data) throws ProtocolException {
		decodePacket(data);
	}

	/*protected void decodePacket(Name extractFrom) throws ProtocolException {
		//labels are restricted to 63 octets or les
		String toParse = extractFrom.getLabelString(0);
		byte[] rawBytes = Base16Alpha.decodeBase16(toParse);
		decodePacket(rawBytes);
	}*/

	
	public static ClientPacket decodeClientPacket(Name name, String domain) throws IOException {
		String toParse = name.toString();//getLabelString(0);
		//remove the domain name leading and trailing
		int stripTo = toParse.lastIndexOf("." + domain + ".");
		toParse = toParse.substring(0, stripTo);
		//remove all dots
		toParse = toParse.replaceAll("\\.", "");
		
		byte[] rawBytes;
		byte [] decodeStringBytes = toParse.getBytes();
		switch (decodeStringBytes[0]) {
		case 'a':
			rawBytes = Base16Alpha.decodeBase16(decodeStringBytes, 1);
			break;
		case 'b': {
			byte [] pktSizeBytes = {0,0};
			int bytesRead = base63Converter.decode(decodeStringBytes, 1, decodeStringBytes.length - 1, 2, pktSizeBytes);
			int pktSize = (pktSizeBytes[0]&0xff) | ((pktSizeBytes[1]&0xff) << 8);
			rawBytes = new byte[pktSize];
			base63Converter.decode(decodeStringBytes, 1 + bytesRead, decodeStringBytes.length - 1 - bytesRead, pktSize, rawBytes);
			}
			break;
		default:
			throw new ProtocolException("Bad encoding type");
		}
		
		if (rawBytes.length < FIXED_HEADER_SIZE) {
			throw new ProtocolException("Packet too small");
		}
		
		if (0 != (rawBytes[Packet.OFFSET_FLAGS] & Packet.FLAG_SPECIAL)) {
			switch (rawBytes[Packet.FIXED_HEADER_SIZE + SpecialClientPacket.OFFSET_SPECIAL_TYPE]) {
			case SpecialClientPacket.SPECIAL_TYPE_CONNECTION_REQUEST:
				return new ConnectionRequestClientPacket(rawBytes);
			case SpecialClientPacket.SPECIAL_TYPE_CONNECTION_CLOSED:
				return new ConnectionClosedClientPacket(rawBytes);
			default:
				throw new ProtocolException("Bad special type on special packet.");
			}
		}
		return new ClientPacket(rawBytes);
	}
	
}
