package com.eactive.eai.common.util;

import com.eactive.eai.common.bizkey.BizKeyFldVO;
import com.eactive.eai.common.bizkey.BizKeyManager;
import com.eactive.eai.common.bizkey.BizKeyVO;
import com.eactive.eai.common.message.MessageType;
import com.eactive.eai.transformer.function.util.CodeConversion;
import com.eactive.eai.transformer.layout.LayoutTypeKey;
import com.eactive.eai.transformer.message.*;
import com.eactive.eai.transformer.util.MemoryLogger;
import org.apache.commons.lang3.StringUtils;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

// Inbound 에서 업무추적필드값, ALT-KEY값을 추출하는 기능을 제공
public final class BizKeyExtractor {

	static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);

	private BizKeyExtractor() {

	}

	public static boolean isHex(String eaiSvcCd) {
		BizKeyManager manager = BizKeyManager.getInstance();
		BizKeyVO bizKey = manager.getBizKey(eaiSvcCd + "TR");
		if (bizKey == null)
			return false;
		if ("HEX".equals(bizKey.getBizKeyFld(0).getMsgTp())) {
			return true;
		}
		return false;
	}

	private static Message setMessageValue(Message msg, Object message) throws Exception {
		String msgType = ((Message) msg).getLayout().getLayoutType().getName();
		if (LayoutTypeKey.XML.equals(msgType)) {
			String rootItemName = msg.getName();
			String xmlString = "";

			xmlString = "<" + rootItemName + ">" + (String) message + "</" + rootItemName + ">";

			try {
				msg.setData(xmlString);
			} catch (MessageSetDataException e) {
				MemoryLogger.error("BizKeyExtractor | setData error", e);
				throw e;
			}
		} else if (LayoutTypeKey.JSON.equals(msgType)) {
			String rootItemName = msg.getName();
			String jsonString = (String) message;
			try {
				JSONObject value = (JSONObject) JSONValue.parse(jsonString);
				JSONObject root = new JSONObject();
				root.put(rootItemName, value);
				jsonString = root.toJSONString();
				msg.setData(jsonString);
			} catch (MessageSetDataException e) {
				MemoryLogger.error("BizKeyExtractor | setData error", e);
				throw e;
			}
		} else {
			try {
				msg.setData(message);
			} catch (MessageSetDataException e) {
				MemoryLogger.error("BizKeyExtractor | setData error", e);
				throw e;
			}
		}
		return msg;
	}

	public static String getBizKeyValue(String eaiSvcCd, String messageID, Object message) throws Exception {
		String key = "";
		try {
			BizKeyManager manager = BizKeyManager.getInstance();
			BizKeyVO bizKey = manager.getBizKey(eaiSvcCd + "TR");
			String tmp = ""; // Transformer 호출

			if (bizKey != null) {
				// tobe 추가 로직
				// 1. 참조메시지가 없어도 추적키의 레이아웃으로 추출
				// 2. 참조메시지가 있다면 추적키의 레이아웃을 바꿔치기함
				Message msg = null;
				if (StringUtils.isEmpty(messageID)) {
					BizKeyFldVO keyFld = bizKey.getBizKeyFld(0);
					if (keyFld == null) {
						throw new Exception("not found bizKey");
					}
					String bizMessageID = keyFld.getBwkColNm();
					bizMessageID = bizMessageID.substring(0, bizMessageID.indexOf("."));
					msg = MessageFactory.getFactory().getMessage(bizMessageID);
				} else {
					msg = MessageFactory.getFactory().getMessage(messageID);
				}

				msg = setMessageValue(msg, message);

				int fldSize = bizKey.getBizKeyFldLength();
				for (int i = 0; i < fldSize; i++) {
					BizKeyFldVO keyFld = bizKey.getBizKeyFld(i);
					if (keyFld == null) {
						throw new Exception("BizKeyFldVO is null - " + i);
					}
					String colName = keyFld.getBwkColNm();
					if (colName != null) {
						colName = colName.trim();
						if (colName.length() > 0) {
							if ((msg instanceof EbcdicMessage || msg instanceof CommonEbcdicMessage)
									|| "EBC".equals(keyFld.getMsgTp())) {
								tmp = new String(CodeConversion.seToAsc(msg.getByteArray(colName)));
							} else {
								tmp = msg.getString(colName);
							}
							key = key + tmp;
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("getBizKeyValue error", e);
			// throw new Exception("RECEAICBE001");
//            throw new Exception(ExceptionUtil.getErrorCode(e,"RECEAICBE001"), e);
			throw e;
		}
		return key;
	}

	public static String[] getAltKeyValues(String eaiSvcCd, String messageID, Object message) throws Exception {
		String[] key = new String[4];
		try {
			BizKeyManager manager = BizKeyManager.getInstance();
			BizKeyVO bizKey = manager.getBizKey(eaiSvcCd + "AK");

			if (bizKey != null) {

				// tobe 추가 로직
				// 1. 참조메시지가 없어도 추적키의 레이아웃으로 추출
				// 2. 참조메시지가 있다면 추적키의 레이아웃을 바꿔치기함
				Message msg = null;
				if (StringUtils.isEmpty(messageID)) {
					BizKeyFldVO keyFld = bizKey.getBizKeyFld(0);
					if (keyFld == null) {
						throw new Exception("not found bizKey");
					}
					String bizMessageID = keyFld.getBwkColNm();
					bizMessageID = bizMessageID.substring(0, bizMessageID.indexOf("."));
					msg = MessageFactory.getFactory().getMessage(bizMessageID);
				} else {
					msg = MessageFactory.getFactory().getMessage(messageID);
				}

				int fldSize = bizKey.getBizKeyFldLength();

				msg = setMessageValue(msg, message);

				String tmp = ""; // Transformer 호출
				for (int i = 0; i < fldSize; i++) {
					if (i >= 4)
						break; // ALT-KEY는 4개가 최대값이다.
					BizKeyFldVO keyFld = bizKey.getBizKeyFld(i);

					if (keyFld == null) {
						throw new Exception("BizKeyFldVO is null - " + i);
					}

					String colName = keyFld.getBwkColNm();
					if (colName != null) {
						colName = colName.trim();
						if (colName.length() > 0) {
							if (msg instanceof EbcdicMessage) {
								key[i] = new String(CodeConversion.seToAsc(msg.getByteArray(colName)));
							} else {
								key[i] = tmp = msg.getString(colName);
							}
						} else {
							key[i] = "";
						}
					} else {
						key[i] = "";
					}
				}
			} else {
				return new String[] { "", "", "", "" };
			}
		} catch (Exception e) {
			// e.printStackTrace();
			// throw new Exception("RECEAICBE010");
//            throw new Exception(ExceptionUtil.getErrorCode(e,"RECEAICBE010"), e);
			throw e;
		}
		return key;
	}

	public static String getBizKeyCode(String bizCodeData, Object message, boolean isEbcdic) throws Exception {
		if (message == null)
			return "";

		String keys = "";
		byte[] key = null;
		byte[] msg = null;
		if (message instanceof byte[]) {
			msg = (byte[]) message;
		} else if (message instanceof String) {
			msg = ((String) message).getBytes();
		} else {
			return "";
		}

		if (bizCodeData != null && !"".equals(bizCodeData.trim())) {
			Matcher matcher = Pattern.compile("\\[([ ]*[0-9]+)[ ]*,([ ]*[0-9]+)[ ]*\\]").matcher(bizCodeData.trim());
			while (matcher.find()) {
				int offset = Integer.parseInt(matcher.group(1).trim());
				int length = Integer.parseInt(matcher.group(2).trim());
				if (msg.length < offset + length) {
					continue;
				}
				key = new byte[length];
				System.arraycopy(msg, offset, key, 0, length);
				if (isEbcdic) {
					keys = keys + (new String(CodeConversion.seToAsc(key)).trim());
				} else {
					keys = keys + (new String(key)).trim();
				}
			}
		}
		return keys;

	}
//	   public static void main(String args[]) throws Exception {
//	   test();
//}

// private static void test() throws Exception {
//    	String bizCodeData = "[0,4][4,2]";
//    	byte[] message = "1234567890ABCD".getBytes();
//    	boolean isEbcdic = false;
//
//    	String s = BizKeyExtractor.getBizKeyCode(bizCodeData, message, isEbcdic);
//    	System.out.println(s);
//    }
}