/**
 * @author	STF 424_ITS_Test_Platform
 * @version    $URL$
 *             $Id$
 */
package org.etsi.its.codec.adapter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.logging.Logger;

import org.etsi.common.ByteHelper;
import org.etsi.its.codec.IEnumConverter;
import org.etsi.its.codec.TestAdapterMessageTypeEnum;

/**
 * This class provides a codec to encode/decode TLV messages exchanged between TTCN-3 and Test Adapter
 */
public class LibItsInterfaceCodecImpl implements ICodec {

	/**
	 * Module version
	 */
	public static final String Version = "1.0.0.0";

	/**
	 * Logger instance
	 */
	private final static Logger _logger = Logger.getLogger("org.etsi.its");

	/**
	 * The built list of TLV elements during decoding operation
	 */
//	private LinkedHashMap<TestAdapterMessageTypeEnum, ByteArrayOutputStream> _typeIds;

	/**
	 * Constructor
	 */
	public LibItsInterfaceCodecImpl() {
		_logger.entering("LibItsInterfaceCodecImpl", "Constructor", String.format("version:%s", Version));

//		_typeIds = null;
	}

	/**
	 * Decodes the specified message
	 * 
	 * @param message The message to decode in bytes format
	 * @return A list of TLV sequences
	 */
	@Override
	public IValue Decode(final byte[] message) {
		// Sanity checks
		if ((message == null) || (message.length == 0)) {
			return null;
		}

		return null;
	}

	/**
	 * Encode the specified type/value into a TLV sequence
	 * 
	 * @param type The type to encode
	 * @param buffer The value for this type
	 * @param timestamp Reception time
	 * @return A TLV sequence in byte format
	 * @throws IOException Signals that an I/O exception of some sort has occurred
	 */
	@Override
	public byte[] Encode(final IEnumConverter type, final byte[] buffer, final long timestamp) throws IOException {
		_logger.entering("LibItsInterfaceCodecImpl", "Encode", String.format("type: %s", type.name()));

		ByteArrayOutputStream value = new ByteArrayOutputStream();
		value.write(type.convert());
		if ((buffer == null) || (buffer.length == 0)) {
			value.write((byte)0x00); // Length
			value.write((byte)0x00);
		} else {
			switch ((TestAdapterMessageTypeEnum)type) {
				case CamInd:
					value.write(ByteHelper.intToByteArray(buffer.length, 2));
					value.write(buffer);
					break;
				case DenmInd:
					// Store buffer
					value.write(ByteHelper.intToByteArray(buffer.length, 2));
					value.write(buffer);
					// Store time stamp
					value.write(TestAdapterMessageTypeEnum.receptionTime.convert());
					value.write(ByteHelper.intToByteArray(Long.SIZE / Byte.SIZE, 2));
					value.write(ByteHelper.longToByteArray(timestamp, Long.SIZE / Byte.SIZE));
					break;
				case GeoNetworkingInd:
					value.write(ByteHelper.intToByteArray(3 + buffer.length, 2));
					value.write(TestAdapterMessageTypeEnum.GeoNetworkingPacket.convert());
					value.write(ByteHelper.intToByteArray(buffer.length, 2));
					value.write(buffer);
					break;
				case IPv6OverGeoNetworkingInd:
					value.write(ByteHelper.intToByteArray(buffer.length, 2));
					value.write(buffer);
					break;
				case BtpInd:
					value.write(ByteHelper.intToByteArray(3 + buffer.length, 2));
					value.write(TestAdapterMessageTypeEnum.BtpPacket.convert());
					value.write(ByteHelper.intToByteArray(buffer.length, 2));
					value.write(buffer);
					break;
				case BtpAHeader:
					// No break;
				case BtpBHeader: // Bad design in BTP which breaks layer independence
					value.write(ByteHelper.intToByteArray(buffer.length, 2));
					value.write(buffer);
					break;
				default:
					throw new RuntimeException(String.format("Not implemented type class %s", type.name()));
			} // End of 'switch' statement
		}
		
//		if (_logger.isLoggable(Level.ALL)) ByteHelper.dump("LibItsInterfaceCodecImpl.Encode: ", value.toByteArray());
		return value.toByteArray();
	} // End of method Encode

} // End of class LibItsInterfaceCodecImpl
