/**
 * Copyright 2008-2009 DRIVER PROJECT (ICM UW)
 * Original author: Marek Horst
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package eu.dnetlib.common.profile.utils;

import java.util.Iterator;
import java.util.List;

import eu.dnetlib.common.profile.ProfileHeader;
import eu.dnetlib.common.profile.Protocol;
import eu.dnetlib.common.profile.blackboard.Blackboard;
import eu.dnetlib.common.profile.blackboard.IBlackboardMessage;
import eu.dnetlib.common.profile.blackboard.Parameter;


/**
 * Class used for converting object data  into profile string representation.
 * @author mhorst
 *
 */
public class ProfileMarshaller {
	
	/**
	 * Generates xml representation of ProfileHeader object.
	 * @param profileHeader
	 * @return
	 */
	public static String generateProfileHeader(ProfileHeader profileHeader) {
		if (profileHeader == null)
			return null;
		StringBuffer strBuff = new StringBuffer("<HEADER>");
		strBuff.append("<RESOURCE_IDENTIFIER value=\""
				+ profileHeader.getResourceIdentifier() + "\"/>");
		strBuff.append("<RESOURCE_TYPE value=\""
				+ profileHeader.getResourceType() + "\"/>");
		strBuff.append("<RESOURCE_KIND value=\""
				+ profileHeader.getResourceKind() + "\"/>");
		if (profileHeader.getResourceURI() != null)
			strBuff.append("<RESOURCE_URI value=\""
					+ profileHeader.getResourceURI() + "\"/>");
		else
			strBuff.append("<RESOURCE_URI value=\"\"/>");
		
		if (profileHeader.getDateOfCreation() != null)
			strBuff.append("<DATE_OF_CREATION value=\""
					+ profileHeader.getDateOfCreation() + "\"/>");
		else
			strBuff.append("<DATE_OF_CREATION value=\"\"/>");

		if (profileHeader.getParentId() != null)
			strBuff.append("<PARENT_ID value=\"" + profileHeader.getParentId()
					+ "\" type=\"" +  profileHeader.getParentType()
					+ "\"/>");
		
		if (profileHeader.getProtocols()!=null && profileHeader.getProtocols().size()>0) {
			strBuff.append("<PROTOCOLS>");
			Iterator<Protocol> itProtocol = profileHeader.getProtocols().iterator();
			while (itProtocol.hasNext()) {
				Protocol currentProtocol = itProtocol.next();
				strBuff.append("<PROTOCOL address=\"");
				strBuff.append(currentProtocol.getAddress());
				strBuff.append("\" name=\"");
				strBuff.append(currentProtocol.getName());
				strBuff.append("\"/>");
			}
			strBuff.append("</PROTOCOLS>");
		}
		
		strBuff.append("</HEADER>");
		return strBuff.toString();
	}
	
	/**
	 * Generates simple profile with blackboard body part.
	 * Returns xml profile representation.
	 * @param profileHeader
	 * @param blackboard
	 * @return xml profile representation
	 */
	public static String generateBBProfile(ProfileHeader profileHeader, Blackboard blackboard) {
		return generateBBProfile(profileHeader, blackboard, null);
	}
	
	/**
	 * Generates simple profile with blackboard body part and additional body part passed as String param.
	 * Returns xml profile representation.
	 * @param profileHeader
	 * @param blackboard
	 * @param additionalBodyPart
	 * @return xml profile representation
	 */
	public static String generateBBProfile(ProfileHeader profileHeader, Blackboard blackboard,
			String additionalBodyPart) {
		StringBuffer strBuff = new StringBuffer("<RESOURCE_PROFILE>");
		String profileHeaderPartStr = generateProfileHeader(profileHeader);
		if (profileHeaderPartStr!=null)
			strBuff.append(profileHeaderPartStr);
		strBuff.append("<BODY>");
		String blackboardPartStr = generateBlackboardPartOfProfile(blackboard);
		if (blackboardPartStr!=null)
			strBuff.append(blackboardPartStr);
		if (additionalBodyPart!=null)
			strBuff.append(additionalBodyPart);
		strBuff.append("</BODY>");
		strBuff.append("</RESOURCE_PROFILE>");
		return strBuff.toString();
	}
	
	/**
	 * Generates Message part of Blackboard.
	 * Returns xml representation of Message object.
	 * @param messages
	 * @return xml representation of Message object
	 */
	public static String generateMessagePartOfBlackBoard(List<IBlackboardMessage> messages) {
		if (messages==null)
			return null;
		StringBuffer strBuff = new StringBuffer();
		Iterator<IBlackboardMessage> it = messages.iterator();
		while (it.hasNext()) {
			IBlackboardMessage message = it.next();
			strBuff.append("<MESSAGE date=\"");
			strBuff.append(message.getDate());
			strBuff.append("\" id=\"");
			strBuff.append(message.getId());
			strBuff.append("\">");
			strBuff.append("<ACTION>");
			strBuff.append(message.getAction());
			strBuff.append("</ACTION>");
			if (message.getParamList()!=null) {
				Iterator<Parameter> itParam = message.getParamList().iterator();
				while (itParam.hasNext()) {
					Parameter currentParam = itParam.next();
					strBuff.append("<PARAMETER value=\"");
					strBuff.append(normalizeAttributeValue(currentParam.getValue()));
					strBuff.append("\" name=\"");
					strBuff.append(currentParam.getName());
					strBuff.append("\"/>");
				}
			}
			strBuff.append("<ACTION_STATUS>");
			strBuff.append(message.getActionStatus());
			strBuff.append("</ACTION_STATUS>");
			strBuff.append("</MESSAGE>");
		}
		return strBuff.toString();
	}
	
	/**
	 * Generates Message part of Blackboard.
	 * Returns xml representation of Message object.
	 * @param message
	 * @return xml representation of Message object
	 */
	public static String generateMessagePartOfBlackBoard(IBlackboardMessage message) {
		if (message==null)
			return null;
		StringBuffer strBuff = new StringBuffer();
		strBuff.append("<MESSAGE date=\"");
		strBuff.append(message.getDate());
		strBuff.append("\" id=\"");
		strBuff.append(message.getId());
		strBuff.append("\">");
		strBuff.append("<ACTION>");
		strBuff.append(message.getAction());
		strBuff.append("</ACTION>");
		if (message.getParamList()!=null) {
			Iterator<Parameter> itParam = message.getParamList().iterator();
			while (itParam.hasNext()) {
				Parameter currentParam = itParam.next();
				strBuff.append("<PARAMETER value=\"");
				strBuff.append(normalizeAttributeValue(currentParam.getValue()));
				strBuff.append("\" name=\"");
				strBuff.append(currentParam.getName());
				strBuff.append("\"/>");
			}
		}
		strBuff.append("<ACTION_STATUS>");
		strBuff.append(message.getActionStatus());
		strBuff.append("</ACTION_STATUS>");
		strBuff.append("</MESSAGE>");
		return strBuff.toString();
	}
	
	/**
	 * Performs XML attribute normalization.
	 * @param source
	 * @return normalized XML attribute
	 */
	protected static String normalizeAttributeValue(String source) {
//		TODO this is basic implementation, find dedicated utility if available
		if (source!=null) {
			return source.replace('\n', ' ').replace('\t', ' ').replace('\r', ' ')
			.replace("<", "&lt;").replace(">", "&gt;").trim();
		} else {
			return null;
		}
	}
	
	/**
	 * Generates xml representation of blackboard object.
	 * @param blackboard
	 * @return xml representation of blackboard object
	 */
	public static String generateBlackboardPartOfProfile(Blackboard blackboard) {
		if (blackboard==null)
			return null;
		StringBuffer strBuff = new StringBuffer("<BLACKBOARD>");
		if (blackboard.getLastRequest()!=null) {
			if (blackboard.getLastRequest().getValue()!=null) {
				strBuff.append("<LAST_REQUEST date=\"");
				strBuff.append(blackboard.getLastRequest().getDate());
				strBuff.append("\">");
				strBuff.append(blackboard.getLastRequest().getValue());
				strBuff.append("</LAST_REQUEST>");
			} else {
				strBuff.append("<LAST_REQUEST />");
			}
		}
		if (blackboard.getLastResponse()!=null) {
			if (blackboard.getLastResponse().getValue()!=null) {
				strBuff.append("<LAST_RESPONSE date=\"");
				strBuff.append(blackboard.getLastResponse().getDate());
				strBuff.append("\">");
				strBuff.append(blackboard.getLastResponse().getValue());
				strBuff.append("</LAST_RESPONSE>");
			} else {
				strBuff.append("<LAST_RESPONSE />");
			}
		}
		String messagePartString = generateMessagePartOfBlackBoard(blackboard.getMessages());
		if (messagePartString!=null) {
			strBuff.append(messagePartString);
		}
		strBuff.append("</BLACKBOARD>");
		return strBuff.toString();
	}

	
}
