package com.cim.idm.wmsextend.generic.util;

import com.cim.idm.framework.util.xml.JdomUtils;
import com.tibco.tibrv.TibrvException;
import com.tibco.tibrv.TibrvMsg;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.Document;
import org.jdom.Element;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SMessageUtil {

	private static 	Log 								log = LogFactory.getLog(SMessageUtil.class);

	public static final String 							BPELName_Tag = "bpelname";
	public static final String 							Message_Tag = "Message";
	public static final String 							MessageName_Tag = "MESSAGENAME";
	public static final String 							Header_Tag = "Header";
	public static final String                          Listener_Tag = "listener";
	public static final String 							Body_Tag = "Body";
	public static final String 							Result_Name_Tag				= "Return";
	public static final String							Result_ReturnCode			= "RETURNCODE";
	public static final String							Result_ErrorMessage			= "RETURNMESSAGE";

	public static final String                          DataFieldName = "Message";

	public static final String                          DataFieldNameXmlData = "xmlData";

	private static final String 						ReplySubjectName_Tag = "ORIGINALSOURCESUBJECTNAME";

	public static final String							dataField_TAG = "Message";

	//ERP升级-新增字段
	private static final String 						Interface_ID = "interfaceID";
	private static final String 						Trans_ID = "transID";
	private static final String 						Message_ID = "messageID";
	private static final String 						Sender = "sender";
	private static final String 						Receiver = "receiver";
	private static final String 						appID = "appID";
	private static final String 						appToken = "appToken";


	/***
	 *
	 * @param messageName
	 * @param siteName
	 * @param shopName
	 * @param machineName
	 * @param transactionId
	 * @param originalSourceSubjectName
	 * @param sourceSubjectName
	 * @param targetSubjectName
	 * @param eventUser
	 * @param eventComment
	 * @return
	 */
	public static Document createPMSMessageDocument(String messageName,String siteName,String shopName,
													String machineName,String transactionId,String originalSourceSubjectName,String sourceSubjectName,
													String targetSubjectName,String eventUser,String eventComment){
		Element message = new Element( Message_Tag );
		Element header = new Element( Header_Tag );
		Document document = new Document( message );
		message.addContent(header);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, MessageName_Tag, messageName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "SITENAME", siteName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "SHOPNAME", shopName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "MACHINENAME", machineName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "TRANSACTIONID", transactionId);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "ORIGINALSOURCESUBJECTNAME", originalSourceSubjectName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "SOURCESUBJECTNAME", sourceSubjectName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "TARGETSUBJECTNAME", targetSubjectName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "EVENTUSER", eventUser);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "EVENTCOMMENT", eventComment);
		Element body = new Element( Body_Tag );
		message.addContent(body);
		return document;
	}

	public static void setBodyItemValue(Document doc, String nodeName, String nodeValue){
		if (doc.getRootElement().getChild(Body_Tag) == null)
			doc.getRootElement().addContent(new Element(Body_Tag));

		String nodePath = "//" + Message_Tag + "/" + Body_Tag + "/";
		setElement(nodePath, doc, nodeName, nodeValue);

		if (nodeName.equalsIgnoreCase(SMessageUtil.Result_ReturnCode) && !nodeValue.equalsIgnoreCase("0"))
			log.error(nodeName + " : " + nodeValue);
		else if (nodeName.equalsIgnoreCase(SMessageUtil.Result_ErrorMessage) && nodeValue.length() > 0)
			log.error(nodeName + " : " + nodeValue);
		else if  (nodeName.equalsIgnoreCase(SMessageUtil.Result_ErrorMessage) && nodeValue.length() == 0)
			log.error(nodeName + " : ");
	}

	public static Document createMESXmlDocument(String MessageName, String TransactionID, String OriginalSourceSubjectName, String SourceSubjectName, String TargetSubjectName, String EventUser,String EventComment)
	{
		Element message = new Element( Message_Tag );
		Document document = new Document( message );
		Element header = new Element( Header_Tag );
		message.addContent(header);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, MessageName_Tag, MessageName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "TRANSACTIONID", TransactionID);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, ReplySubjectName_Tag, OriginalSourceSubjectName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "SOURCESUBJECTNAME", SourceSubjectName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "TARGETSUBJECTNAME", TargetSubjectName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "EVENTUSER", EventUser);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "EVENTCOMMENT", EventComment);
		Element body = new Element( Body_Tag );
		message.addContent(body);
		return document;
	}

	//ERP升级-新增方法
	public static Document createTQMSXmlDocument(String MessageName,String EventComment)
	{
		Element message = new Element( Message_Tag);
		Document document = new Document( message );
		Element header = new Element( Header_Tag );
		message.addContent(header);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, Interface_ID, MessageName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, Trans_ID, EventComment);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, Message_ID, MessageName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, Sender, "B20WMS");
		setElement("//" + Message_Tag + "/" + Header_Tag , document, Receiver, "TQMS");
		setElement("//" + Message_Tag + "/" + Header_Tag , document, appID, "");
		setElement("//" + Message_Tag + "/" + Header_Tag , document, appToken, "");
		Element body = new Element( Body_Tag );
		message.addContent(body);
		return document;
	}

	public static Document createMESXmlDocument(String MessageName,String EventComment)
	{
		Element message = new Element( Message_Tag );
		Document document = new Document( message );
		Element header = new Element( Header_Tag );
		message.addContent(header);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, MessageName_Tag, MessageName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "ORIGINALSOURCESUBJECTNAME", EventComment);
		Element body = new Element( Body_Tag );
		message.addContent(body);
		return document;
	}

	/***
	 *
	 * @param nodePath : The path that create new element
	 * @param parentElement
	 * @param nodeName
	 * @param nodeValue
	 */
	public static void createElement(String nodePath, Element parentElement,String nodeName, String nodeValue)
	{
		if (nodeValue == null) nodeValue = "";
		try {
			if (nodePath.substring(nodePath.length()-1 , nodePath.length()).equalsIgnoreCase("/"))
				nodePath = nodePath.substring(0, nodePath.length()-1);
			//Element parentElement = JdomUtils.getNode(doc, nodePath);
			Element newElement = JdomUtils.addElement(parentElement, nodeName, nodeValue);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 *Create xml document
	 *Return as below
	 *<Message>
	 *	<Header>
	 *	</Header>
	 *	<Body>
	 *	</Body>
	 *</Message>
	 */
	public static Document createERPXmlDocument(String MessageName,String EventComment)
	{
		Element message = new Element( Message_Tag );
		Document document = new Document( message );
		Element header = new Element( Header_Tag );
		message.addContent(header);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, MessageName_Tag, MessageName);
		setElement("//" + Message_Tag + "/" + Header_Tag , document, "EVENTCOMMENT", EventComment);
		Element body = new Element( Body_Tag );
		message.addContent(body);
		return document;
	}

	/*
	 *Create BADT xml document
	 *Return as below
	 *<Message>
	 *	<Header>
	 *	</Header>
	 *	<Body>
	 *	</Body>
	 *</Message>
	 */
	public static Document createERPXmlDocumentForBadt()
	{
		Element message = new Element( "IV_REQUEST" );
		Document document = new Document( message );
		//Element header = new Element( Header_Tag );
		//message.addContent(header);
		//setElement("//" + Message_Tag + "/" + Header_Tag , document, MessageName_Tag, MessageName);
		//setElement("//" + Message_Tag + "/" + Header_Tag , document, "EVENTCOMMENT", EventComment);
		//Element body = new Element( Body_Tag );
		//message.addContent(body);
		return document;
	}

	/*
	 * Name : getListenerBpelName
	 * Desc : This function is getListenerBpelName
	 * Author : BIDM Systems, Inc
	 * Date : 2015.01.04
	 */
	public static String getListenerBpelName(Document doc)
	{
		String Listener = null;
		try {
			Listener = (String) JdomUtils.getNodeText(doc, "//" + Message_Tag + "/" + Header_Tag + "/" + Listener_Tag);
			if (Listener != null && Listener.length() > 0) {
				if (!Listener.toLowerCase().endsWith(".bpel"))
					Listener = Listener + ".bpel";
			}
		} catch (Exception e) {
		}
		return Listener;
	}
	/*
	 * Name : getBpelName
	 * Desc : This function is getBpelName
	 * Author : BIDM Systems, Inc
	 * Date : 2015.01.04
	 */
	public static String getBpelName(Document doc)
	{
		String BpelName = null;
		try {
			BpelName = (String) JdomUtils.getNodeText(doc, "//" + Message_Tag + "/" + Header_Tag + "/" + MessageName_Tag);
			if (BpelName != null && BpelName.length() > 0) {
				if (!BpelName.toLowerCase().endsWith(".bpel"))
					BpelName = BpelName + ".bpel";
			}
		} catch (Exception e) {
		}
		return BpelName;
	}
	/*
	 * Name : getDocumentFromTibrvMsg
	 * Desc : This function is getDocumentFromTibrvMsg
	 * Author : BIDM Systems, Inc
	 * Date : 2015.01.04
	 */
	public static Document getDocumentFromTibrvMsg(TibrvMsg data, String dataFieldTag)
	{

		Document document = null;
		String strMsg = "";
		String replySubjectName = "";
		if (data instanceof TibrvMsg)
		{
			TibrvMsg TibrvMsg = (TibrvMsg)data;
			try {
				strMsg = (String)TibrvMsg.get(dataFieldTag);

				if( strMsg == null )
					strMsg = (String)TibrvMsg.get(dataFieldTag);

				replySubjectName = (String)TibrvMsg.getReplySubject();
				if (replySubjectName == null) replySubjectName = "";

			} catch (TibrvException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		try {
			document = JdomUtils.loadText(strMsg);
		} catch (Exception e)
		{
			try {
				document = createXmlDocument(strMsg);
			} catch (Exception ex) {
				log.error(ex, ex);
			}
		}
		if ( replySubjectName.length() > 0 )
			setItemValue(document, Header_Tag, ReplySubjectName_Tag, replySubjectName);
		return document;
	}
	/*
	 * Name : replyXMLMessage
	 * Desc : This function is replyXMLMessage
	 * Author : BIDM Systems, Inc
	 * Date : 2015.01.04
	 */
	public static String replyXMLMessage(String ReturnCode)
	{
		Document doc = JdomUtils.createDocument(Message_Tag);
		SMessageUtil.setResultItemValue(doc, Result_ReturnCode, ReturnCode);
		SMessageUtil.setResultItemValue(doc, Result_ErrorMessage, "");
		String replyMSG = JdomUtils.toString(doc);
		return replyMSG;
	}
	/*
	 * Name : setElement
	 * Desc : This function is setElement
	 * Author : BIDM Systems, Inc
	 * Date : 2015.01.04
	 */
	public static void setElement(String nodePath, Document doc, String nodeName, String nodeValue)
	{
		if (nodeValue == null) nodeValue = "";
		try {
			Element element = JdomUtils.getNode(doc, nodePath + nodeName);
			if (element != null) {
				//element.setContent(new CDATA(nodeValue));
				//element.setContent(new Element(nodeValue));
				if (nodePath.substring(nodePath.length()-1 , nodePath.length()).equalsIgnoreCase("/"))
					nodePath = nodePath.substring(0, nodePath.length()-1);
				JdomUtils.setNodeText(doc, nodePath, nodeName, nodeValue);
			}
			else {
				//Element createElement = JdomUtils.createElement(nodeName, valueKey);
				if (nodePath.substring(nodePath.length()-1 , nodePath.length()).equalsIgnoreCase("/"))
					nodePath = nodePath.substring(0, nodePath.length()-1);
				Element parentElement = JdomUtils.getNode(doc, nodePath);
				Element newElement = JdomUtils.addElement(parentElement, nodeName, nodeValue);
				//newElement.setContent(new CDATA(nodeValue));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * Name : setResultItemValue
	 * Desc : This function is setResultItemValue
	 * Author : BIDM Systems, Inc
	 * Date : 2015.01.19
	 */
	public static void setResultItemValue(Document doc, String nodeName, String nodeValue)
	{
		if (doc.getRootElement().getChild(Result_Name_Tag) == null)
			doc.getRootElement().addContent(new Element(Result_Name_Tag));

		String nodePath = "//" + Message_Tag + "/" + Result_Name_Tag + "/";
		setElement(nodePath, doc, nodeName, nodeValue);

		if (nodeName.equalsIgnoreCase(SMessageUtil.Result_ReturnCode) && !nodeValue.equalsIgnoreCase("0"))
			log.info(nodeName + " : " + nodeValue);
//		else if (nodeName.equalsIgnoreCase(SMessageUtil.Result_ReturnCode) && nodeValue.equalsIgnoreCase("0"))
//			log.info(MessageUtil.Return_Code + " : 0");
		else if (nodeName.equalsIgnoreCase(SMessageUtil.Result_ErrorMessage) && nodeValue.length() > 0)
			log.info(nodeName + " : " + nodeValue);
		else if  (nodeName.equalsIgnoreCase(SMessageUtil.Result_ErrorMessage) && nodeValue.length() == 0)
			log.info(nodeName + " : ");

		//log.debug("[" + nodeName + "] = " + nodeValue);
	}
	/*
	 * Name : setReplyListItemValue
	 * Desc : This function is setReplyListItemValue
	 * Author : BIDM Systems, Inc
	 * Date : 2015.01.19
	 */
	public static void setReplyListItemValue(Document doc,String Path, String nodeName, String nodeValue)
	{
		if (doc.getRootElement().getChild(Result_Name_Tag) == null)
			doc.getRootElement().addContent(new Element(Result_Name_Tag));

		String nodePath = "//" + Message_Tag + "/" + Body_Tag + "/" + Path;
		setElement(nodePath, doc, nodeName, nodeValue);

		if (nodeName.equalsIgnoreCase(SMessageUtil.Result_ReturnCode) && !nodeValue.equalsIgnoreCase("0"))
			log.info(nodeName + " : " + nodeValue);
//		else if (nodeName.equalsIgnoreCase(SMessageUtil.Result_ReturnCode) && nodeValue.equalsIgnoreCase("0"))
//			log.info(MessageUtil.Return_Code + " : 0");
		else if (nodeName.equalsIgnoreCase(SMessageUtil.Result_ErrorMessage) && nodeValue.length() > 0)
			log.info(nodeName + " : " + nodeValue);
		else if  (nodeName.equalsIgnoreCase(SMessageUtil.Result_ErrorMessage) && nodeValue.length() == 0)
			log.info(nodeName + " : ");

		//log.debug("[" + nodeName + "] = " + nodeValue);
	}
	/*
	 * Name : createXmlDocument
	 * Desc : This function is createXmlDocument
	 * Author : BIDM Systems, Inc
	 * Date : 2015.01.19
	 */
	public static Document createXmlDocument(String receivedData) throws Exception
	{
		Element message = new Element( Message_Tag );
		Document document = new Document( message );


		int idx = receivedData.indexOf(" ");
		String commandName = receivedData.substring(0, idx).trim();
		HashMap<String, String> messageMap = null;
		messageMap = parsingStringMessage(receivedData);

		Element header = new Element( Header_Tag );

		Element subElement = new Element( BPELName_Tag );
		subElement.setText(commandName);
		header.addContent(subElement);

		subElement = new Element( MessageName_Tag );
		subElement.setText(commandName);
		header.addContent(subElement);
		message.addContent(header);
		Element body = new Element( Body_Tag );
		Element ele = null;
		while (messageMap.keySet().iterator().hasNext())
		{
			String keyName = messageMap.keySet().iterator().next();
			String keyValue = messageMap.remove(keyName);
			ele = new Element( keyName );
			ele.setText( keyValue );
			body.addContent( ele );
		}
		message.addContent(body);
		messageMap.clear();
//		log.debug(JdomUtils.toString(document));
		return document;
	}

	/*
	 * Name : setItemValue
	 * Desc : This function is setItemValue
	 * Author : BIDM Systems, Inc
	 * Date : 2015.01.19
	 */
	public static void setItemValue(Document doc, String elementName, String nodeName, String nodeValue)
	{
		try {
			String nodePath = "//" + Message_Tag + "/" + elementName + "/" + nodeName;
			Element element = JdomUtils.getNode(doc, nodePath);
			if (element != null)
				JdomUtils.setNodeText(doc, nodePath, nodeValue);
			else {
				nodePath = "//" + Message_Tag + "/" + elementName + "/";
				if (nodePath.endsWith("/"))
					nodePath = nodePath.substring(0, nodePath.length()-1);
				Element headerElement = JdomUtils.getNode(doc, nodePath);
				JdomUtils.addElement(headerElement, nodeName, nodeValue);
			}
		} catch (Exception e) {
			log.error(e, e);
		}
	}
	/*
	 * Name : parsingStringMessage
	 * Desc : This function is parsingStringMessage
	 * Author : BIDM Systems, Inc
	 * Date : 2015.01.19
	 */
	private static  HashMap<String, String> parsingStringMessage(String msg)
	{
		String delimeter = "[{X*X}]";

		String msg2 = msg;
		while(true)
		{
			int idx1 = msg2.indexOf("=[");
			int idx2 = msg2.indexOf("]", idx1);
			if (idx1 > 0 && idx2 > 0)
			{
				String a = msg2.substring(idx1+2, idx2);
				if (a.length() == 0)
				{
					msg2 = msg2.substring(idx2+1, msg2.length()); continue;
				}
				String b = org.springframework.util.StringUtils.replace(a, "=", "($%^)");
				msg = org.springframework.util.StringUtils.replace(msg, a, b);
				msg2 = msg2.substring(idx2, msg2.length());
			}
			else break;
		}

		String [] messageSplit = msg.split("=");
		HashMap<String, String> params = new HashMap<String, String>();
		StringBuffer keyNameBuffer = new StringBuffer();
		keyNameBuffer.append("Command").append(delimeter);
		StringBuffer valueBuffer = new StringBuffer();
		for (int i=0; i<messageSplit.length; i++)
		{
			if (getKeyName(messageSplit[i]).length() > 0) {
				keyNameBuffer.append(getKeyName(messageSplit[i])).append(delimeter);
				valueBuffer.append(getValue(messageSplit[i])).append(delimeter);
			}
			else {
				valueBuffer.append(messageSplit[i]).append(delimeter);
			}
		}

		String[] keyNames = org.springframework.util.StringUtils.delimitedListToStringArray(keyNameBuffer.toString(), delimeter);
		String[] keyvalues = org.springframework.util.StringUtils.delimitedListToStringArray(valueBuffer.toString(), delimeter);

		//if (keyNames.length == (keyvalues.length+1))


		for (int i=1; i<keyNames.length; i++)
		{
			if (keyNames[i] == null || keyNames[i].trim().length() == 0) continue;
			try {
				keyvalues[i] = keyvalues[i].trim();
				keyvalues[i] = org.springframework.util.StringUtils.replace(keyvalues[i], "($%^)", "=");
				if (keyvalues[i].startsWith("[") && keyvalues[i].endsWith("]"))
					keyvalues[i] = keyvalues[i].substring(1, keyvalues[i].length()-1);
				params.put(keyNames[i], keyvalues[i].trim());
			} catch (Exception e) {
				params.put(keyNames[i], "");
				log.debug("Value of last data is empty");
			}
		}
		return params;
	}
	/*
	 * Name : getKeyName
	 * Desc : This function is getKeyName
	 * Author : BIDM Systems, Inc
	 * Date : 2015.01.19
	 */
	private static String getKeyName(String partialMsg)
	{
		if (partialMsg.startsWith("[") && partialMsg.endsWith("]"))
			return "";
		String character = "";
		String value = "";
		for (int i=partialMsg.length(); i>0; i--)
		{
			character = partialMsg. substring(i-1, i);
			if (character.equalsIgnoreCase(" "))
			{
				return StringUtils.reverse(value);
			}
			else {
				value += character;
			}
		}
		return "";
	}
	/*
	 * Name : getValue
	 * Desc : This function is getValue
	 * Author : BIDM Systems, Inc
	 * Date : 2015.01.19
	 */
	private static String getValue(String partialMsg)
	{
		partialMsg = StringUtils.removeEnd(partialMsg, getKeyName(partialMsg));
//		try {
//			if (partialMsg.trim().length() == 0)
//				return "";
//		} catch (Exception e) {}
		return partialMsg;
	}


	/*
	 * Name : addReturnBodyElement Desc : This function is addReturnBodyElement Author :
	 * BIDM Systems, Inc Date : 2015.07.30
	 */
	public static Document addReturnBodyElement(Document doc, List<Map<String, Object>> appendReturnData)
	{
		String XPathBody = "//" + SMessageUtil.Message_Tag + "/" + SMessageUtil.Body_Tag;
		JdomUtils.addElement(doc, XPathBody, "DATALIST", "");
		for (int i = 0; i < appendReturnData.size(); i++)
		{
			Map<String, Object> map = appendReturnData.get(i);
			Element Snode = null;
			Snode = new Element("DATA");
			for (String key : map.keySet()) {
				String value = null;

				if (map.get(key) == null)
				{
					value = "";
				}
				else if (map.get(key) instanceof String)
				{
					value = (String) map.get(key);
				}
				else
				{
					value = String.valueOf(map.get(key));
				}

				Element Vnode = null;

				Vnode = new Element(key);
				Vnode.setContent(new org.jdom.CDATA(value));
				Snode.addContent(Vnode);
			}
			doc.getRootElement().getChild(SMessageUtil.Body_Tag).getChild("DATALIST").addContent(Snode);
		}

		return doc;
	}

	/*
	 * Name : getElementValue
	 * Desc : This function is getElementValue
	 * Author : BIDM Systems, Inc
	 * Date : 2015.01.30
	 */
	public static String getElementValueByName(Element element, String name)
	{
		if(element != null && element.getChild(name) != null)
		{
			return element.getChild(name).getText();
		}
		else
		{
			return "";
		}
	}

	public static boolean isExistElementName(Element element, String name)
	{
		boolean isExist =  false;

		try{

			element.getChild(name).getName();
			isExist = true;
		}catch (Exception e){
		}

		return isExist;
	}

	public static void addHeaderItemValue(Document doc, String nodeName, String nodeValue)
	{

		String nodePath = "//" + Message_Tag + "/" + Header_Tag + "/";
		setElement(nodePath, doc, nodeName, nodeValue);
	}

	public static void addBodyItemValue(Document doc, String nodeName, String nodeValue)
	{

		String nodePath = "//" + Message_Tag + "/" + Body_Tag + "/";
		setElement(nodePath, doc, nodeName, nodeValue);
	}
	//Add by wwchang 2018.09.10
	public static void setElementValue(Element element, String elementName, String value)
	{
		Element findEle = element.getChild(elementName);
		if(findEle == null)
		{
			Element childElement = new Element(elementName);
			childElement.setText(value);
			element.addContent(childElement);
		}
		else
			findEle.setText(value);
	}
}
