package org.josast.ModuleSoundModem;

import java.util.Arrays;

/**
 *  manage Kiss frame based on KISS protocol
 *  
 *  @see http://www.ka9q.net/papers/kiss.html
 * 
 * @author christophe
 *
 */
public class kiss {

	private static final byte DATA = 0;

	private static final byte  UNKNOW = (byte) 0xF0;

	private static final byte TXDELAY = 1;

	private static final byte P = 2;

	private static final byte SLOTTIME = 3;

	private static final byte TXTAIL = 4;

	private static final byte FULLDUPLEX = 5;

	private static final byte SETHARDWARE = 6;


	private static final byte RETURN = (byte) 0xFF;

	public static final byte FEND = (byte) 0xC0;

	// TFEND ($DB, $DC)

	public static final byte FESC = (byte) 0xDB;
	public static final byte TFEND = (byte) 0xDC;

	// FESC, TFESC ($DB, $DD).
	public static final byte TFESC = (byte) 0xDD;

	byte[] kissdata = null;
	byte type = 0;



	public kiss(final byte[] data) {
		kissdata = data;
	}
	
	public byte getType() {
		return type;
	}

	public void setType(byte type) {
		this.type = type;
	}
	
	/**
	 *  
	 * @return array with data 
	 * @throws KissException
	 */
	public byte[] toRaw() throws KissException {
		byte[] rawData = null;
		rawData = new byte[kissdata.length];
		// identifie le début de trame 
		if (kissdata[0] != FEND) {
			throw new KissException("FEND (0xC0)  value not find at the beginning of the frame ");
		} 
		// vérifie que la fin de trame est bien identifié
		if (kissdata[kissdata.length - 1] != FEND) {
			throw new KissException("FEND (0xC0)  value not find at the end of the frame ");
		}
		// Identifie le type de trame 
		switch (kissdata[1])
		{
		case 0 : type = DATA;
			break;
		case 1 : type = TXDELAY;
		break;  
		case 2 : type = P;
		break;
		case 3 : type = SLOTTIME;
		break;
		case 4 : type = TXTAIL;
		break;
		case 5 : type = FULLDUPLEX;
		break; 
		case 6 : type = SETHARDWARE;
		break;
		case (byte) 0xff: type = RETURN;
		break; 
		
		default : type = UNKNOW;
		
		}
				
		int cptraw = 0;
		int i = 2;
		while (kissdata[i] != FEND) {
			if (kissdata[i] != FESC) {
				rawData[cptraw++] = kissdata[i++];
			} else {
				if (kissdata[i + 1] == TFEND) {
					
					rawData[cptraw++] = FEND;
					i = i + 2;
				} else if (kissdata[i + 1] == TFESC) {
					
					rawData[cptraw++] = FESC;
					i = i +2;
				} else {
					rawData[cptraw++] = kissdata[i++];
				}

			}

		}

		return Arrays.copyOf(rawData, cptraw);

	}

}
