package eu.dnetlib.enabling.aas.ctx.tools;

import org.apache.commons.lang.StringUtils;

/**
 * Decoding and encoding secCtxId from and into a secCtxChain.
 * This implementation doesn't use publ/private key pair. 
 * It requires only the currentChain and CodingContext with secCtxId and profileId provided.
 * @author mhorst
 *
 */
public class V1ContextRecoder implements ICtxRecoder {
	
	public static final String VERSION = "1";
	
	public static final String MAJOR_CHUNK_DELIMITER = ";";
	public static final String MINOR_CHUNK_DELIMITER = "|";

	/* (non-Javadoc)
	 * @see eu.dnetlib.enabling.aas.ctx.tools.ICtxRecoder#decode(eu.dnetlib.enabling.aas.ctx.tools.CodingContext, java.lang.String, byte[])
	 */
	public DecodingResponse decode(CodingContext ctx, String currentChain,
			byte[] otherPubKey) {
		if (currentChain==null)
			return null;
		DecodingResponse response = new DecodingResponse();
		int index = currentChain.indexOf(MAJOR_CHUNK_DELIMITER);
		if (index==-1) {
			response.chain = null;
			CodingContext decodedCtx = decodeCodingContext(currentChain);
			if (decodedCtx!=null) {
				response.secCtxId = decodedCtx.secCtxId;
				response.resourceId = decodedCtx.resourceId;
			}
		} else if (index==currentChain.length()-1) {
			response.chain = null;
			CodingContext decodedCtx = decodeCodingContext(currentChain.substring(0, index));
			if (decodedCtx!=null) {
				response.secCtxId = decodedCtx.secCtxId;
				response.resourceId = decodedCtx.resourceId;
			}
		} else {
			response.chain = currentChain.substring(index+1);
			CodingContext decodedCtx = decodeCodingContext(currentChain.substring(0,index));
			if (decodedCtx!=null) {
				response.secCtxId = decodedCtx.secCtxId;
				response.resourceId = decodedCtx.resourceId;
			}
		}
		return response;
	}

	/* (non-Javadoc)
	 * @see eu.dnetlib.enabling.aas.ctx.tools.ICtxRecoder#encode(eu.dnetlib.enabling.aas.ctx.tools.CodingContext, java.lang.String, byte[])
	 */
	public String encode(CodingContext ctx, String currentChain,
			byte[] otherPubKey) {
		if (ctx==null)
			return currentChain;
		if (currentChain==null)
			return encodeCodingContext(ctx);
		else
			return currentChain + MAJOR_CHUNK_DELIMITER + encodeCodingContext(ctx);
	}

	/* (non-Javadoc)
	 * @see eu.dnetlib.enabling.aas.ctx.tools.ICtxRecoder#identify()
	 */
	public String identify() {
		return VERSION;
	}
	
	/**
	 * Encodes CodingContext into String representation.
	 * @param ctx
	 * @return String representation of CodingContext
	 */
	private String encodeCodingContext(CodingContext ctx) {
		if (ctx==null)
			return "";
		StringBuffer strBuff = new StringBuffer();
		if (ctx.resourceId!=null)
			strBuff.append(ctx.resourceId);
		strBuff.append(MINOR_CHUNK_DELIMITER);
		if (ctx.secCtxId!=null)
			strBuff.append(ctx.secCtxId);
		return strBuff.toString();
	}
	
	/**
	 * Decodes CodingContext from its String representation.
	 * @param encodedCodingContext
	 * @return CodingContext
	 */
	private CodingContext decodeCodingContext(String encodedCodingContext) {
		if (encodedCodingContext==null)
			return null;
		CodingContext ctx = new CodingContext();
		if (!encodedCodingContext.contains(MINOR_CHUNK_DELIMITER)) {
			return ctx;
		} else {
			String[] tokenizedCodingContext = StringUtils.split(
					encodedCodingContext, MINOR_CHUNK_DELIMITER);
			if (tokenizedCodingContext.length==0)
				return ctx;
			else if (tokenizedCodingContext.length==1) {
				if (encodedCodingContext.startsWith(MINOR_CHUNK_DELIMITER))
					ctx.secCtxId = tokenizedCodingContext[0];
				else
					ctx.resourceId = tokenizedCodingContext[0];
			} else {
				ctx.resourceId = tokenizedCodingContext[0];
				ctx.secCtxId = tokenizedCodingContext[1];
			}
			return ctx;
		}
	}
	
	/* (non-Javadoc)
	 * @see eu.dnetlib.enabling.aas.ctx.tools.ICtxRecoder#appendVersionPrefix(java.lang.String)
	 */
	public String appendVersionPrefix(String secCtxChain) {
		if (secCtxChain!=null)
			return VERSION + VERSION_CHAIN_DELIMITER + secCtxChain;
		else
			return VERSION + VERSION_CHAIN_DELIMITER;
	}
}
