/*
 * COMMBiz.java	2011. 03. 17
 *
 * Copyright 2011 FUJITSU KOREA LTD. All rights reserved.
 * FUJITSU KOREA LTD PROPRIETARY/CONFIDENTIAL. 
 * Use is subject to license terms.
 */

package biz.comm;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JOptionPane;

import org.apache.log4j.Logger;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import kr.fujitsu.com.ffw.daemon.core.config.repository.telegram.TelegramUtil;
import kr.fujitsu.com.ffw.util.StringUtil;


/** 
 * COMMBiz
 *  
 * @created  on 1.0,  11/03/17
 * @created  by oki(FUJITSU KOREA LTD.) 
 *  
 * @modified on 
 * @modified by 
 * @caused   by  
 */ 
public class COMMBiz_Master {
	private static Logger logger = Logger.getLogger(COMMBiz_Master.class);

	public static int CM_LENS = 64;			//50에서 변경함. 
	public static int TR_LENS = 185;		//tr log 전문 필드값 
	
	public static String CM_HEADER    = "CM_HEADER";
	public static String TR_HEADER    = "TR_HEADER";

	public static String MASTER_CM_HEADER = "MASTER_CM_HEADER";
	public static String SYSINQ_DATA  = "SYSINQ_DATA";
	public static String JOURNAL_DATA = "JOURNAL_DATA";
										 
	//MSG_TYPE	
	public static int TRAN    = 1;
	public static int JOURNAL = 2;
	public static int DUMMY   = 4;
	public static int SYSINQ  = 6;
	public static int FILE    = 7;	
	public static int MASTER  = 8;
	public static int ERR     = 99;
	//TRAN
	public static String XML_TRAN_SQL         = "tran-sql"; 
	//JOURNAL
	public static String XML_JOURNAL_SQL      = "journal-sql"; 
	                 
	//SYSINQ   
	public static String XML_SYSINQ_SQL       = "sysinq-sql";
	//STSYS   
	public static String XML_STSYS_SQL        = "stsys-sql";
	//POSIrt  
	public static String XML_POSINQ_SQL       = "pos-sql";
	
	//SystemTime
	public static String TB_SEL_STTRP110DT    = "SEL_STTRP110DT";
	//DeployStatus
	public static String TB_UPD_STBDA100AT0   = "UPD_STBDA100AT0"; //마스터생성중 플래그세팅
	public static String TB_UPD_STBDA100AT1   = "UPD_STBDA100AT1"; //마스터생성완료 플래그세팅
	public static String TB_UPD_STBDA100AT2   = "UPD_STBDA100AT2"; //배신결과 플래그세팅(SC용)
	public static String TB_MER_STBDA101AT    = "MER_STBDA101AT";
	//OrderCheck
	public static String TB_SEL_STBDA100AT_1  = "SEL_STBDA100AT_1";
	public static String TB_SEL_STBDA100AT_2  = "SEL_STBDA100AT_2";
	public static String TB_SEL_STBDA100AT_3  = "SEL_STBDA100AT_3";	
	
	

	public static String TB_SEL_SURVEY_INFO  = "SEL_SURVEY_INFO";	
	
	
	public static String TB_SEL_STBDA100AT_01 = "SEL_STBDA100AT_01"; //외식 미사용
	public static String TB_SEL_STBDA100AT_02 = "SEL_STBDA100AT_02"; //외식 미사용
	public static String TB_SEL_STBDA100AT_03 = "SEL_STBDA100AT_03"; //외식 미사용
	
	public static String TB_UPD_STBDA100AT_0  = "UPD_STBDA100AT_0"; //배신결과POS전송 플래그세팅
	public static String TB_UPD_STBDA100AT_1  = "UPD_STBDA100AT_1"; //다운완료POS전송 플래그세팅
	public static String TB_UPD_STBDA100AT_2  = "UPD_STBDA100AT_2"; //적용완료POS전송 플래그세팅
	
	public static String TB_UPD_STBDA120AT_1  = "UPD_STBDA120AT_1";	//배신결과POS전송_NEW 플래그세팅											 
	public static String TB_UPD_STBDA120AT_2  = "UPD_STBDA120AT_2";	//다운완료POS전송_NEW 플래그세팅
	//Device
	public static String TB_DEL_POSDEVICESTATUS = "DEL_POSDEVICESTATUS";	// STBDA111AT 변경 
	public static String TB_DEL_POSSTATUS     	= "DEL_POSSTATUS";			// STBDA110AT
	public static String TB_INS_POSSTATUS     	= "INS_POSSTATUS";			// STBDA110AT 에서 변경
	public static String TB_INS_POSDEVICESTATUS = "INS_POSDEVICESTATUS";
	//TranCall
	public static String TB_SEL_STTRP010DT     = "SEL_STTRP010DT";
	
 
	
	
	public static int TMONEY_FILTER = 1;
	public static int TMONEY_EXT_FILTER = 5;
	public static int CASHBEE_FILTER = 2;
	public static int CASHBEE_MST_FILTER = 3;
	public static int CASHBEE_EXT_FILTER = 4;
	public static int SSGPOINT_FILTER = 6;
	public static int CJPARCEL_FILTER = 7;
	public static int MASTER_EXT_FILTER = 8;
	public static int SSGPAY_FILTER = 9;
	public static int CASHRCPT_FILTER = 10;
	public static int CASHRCPT_EXT_FILTER = 11;
	public static int HANPAY_RT_FILTER = 12;
	public static int HANPAY_ADJ_FILTER = 13;
	public static int RAILPLUS_RT_FILTER = 14;
	public static int RAILPLUS_ADJ_FILTER = 15;
	
	public static final String hexArray = "0123456789ABCDEF";
	
	public static byte[] intToBytes(int value) {
		return new byte[] {
				(byte)(value >>> 8),
				(byte)value};
	}

	public static String bytesToHex(byte[] bytes) {
		if( bytes == null ) {
			return null;
		}
		final StringBuilder hex = new StringBuilder(2 * bytes.length);
		for(final byte b : bytes) {
			hex.append(hexArray.charAt((b & 0xF0) >> 4))
				.append(hexArray.charAt((b & 0x0F)));
		}
		
		return hex.toString();
	}
	
	/***
	 * getDatas
	 * Parse rcvData as msgFormName type and return(rcvData를 msgFormName의 타입으로 파싱한뒤 리턴한다).
	 * @param rcvData
	 * @param msgFormName In case of CM_HEADER, return 42Byte(CM_HEADER인경우 42Byte 리턴) 
	 * @return Receive Message(Receive 메세지) 
	 * @throws Exception
	 */
	public static  HashMap getData(String rcvData, String msgFormName) throws Exception{
		String telegram=rcvData;
			
		// If msgFormName is a header, take the designated header length 42Byte only(msgFormName이 헤더 인경우에는 지정헤더길이 42byte값만 취한다). 
		if (msgFormName.equals(CM_HEADER)){
			telegram = rcvData.substring(0,CM_LENS);
		} else if (msgFormName.equals(TR_HEADER)){
			telegram = rcvData.substring(CM_LENS,CM_LENS+TR_LENS);
		} else if (msgFormName.equals(MASTER_CM_HEADER)){
			telegram = rcvData.substring(0, CM_LENS);
		} else {
			telegram = toData(rcvData);
		}

		return (HashMap)TelegramUtil.bind(telegram, msgFormName);		
	}
	
	/***
	 * toData : Data part message(데이타부 메세지)
	 * @param msg
	 * @return : Data Part (Message value excluding front header 42 bytes out of received data)(데이타부(수신받은 데이타중 앞부분헤더 42바이트를 제외한 메세지값))
	 */
	private static String toData(String msg){
		return msg.substring(COMMBiz_Master.CM_LENS, msg.length());
	}
	
	/***
	 * getCommMsgType 
	 * If MSG_TYPE is not matched with the parameter type, return FALSE(이 파라미터 type과 일지하는 지 확인하여 일치하지 않으면 FALSE리턴)  
	 * @param hm : MSG_TYPE Data(MSG_TYPE데이타) 
	 * @param type
	 * @return TRUE:Matched(일치), False:Not Matched(불일치) 
	 */
	public static boolean getCommMsgType(HashMap hm, int type) {	
		int ret = toInteger((String)hm.get("MSG_TYPE"), 99);	
		
		if (ret != 99) {
			if (type == ret) return true;			
		}
				
		return false;
	}
	
	/***
	 * getCommTranYMD ---> SALE_DT 로 변경
	 * Return TRAN_YMD value(TRAN_YMD값을 리턴) 
	 * @param hm
	 * @return TRANYMD
	 */
	public static String getCommTranYMD(HashMap hm) {		
		return (String)hm.get("SALE_DT");	
	}
	
	/***
	 * getTranType
	 * @param hm
	 * @return TRAN_TYPE
	 */
	public static int getTranType(HashMap hm) {
		return toInteger((String)hm.get("TRAN_TYPE"), ERR);
	}

	/***
	 * toInteger
	 * @param value
	 * @param errRet If not number, return value(숫자가 아닐경우 return value)
	 * @return
	 */
	public static int toInteger(String value, int errRet){
		int ret=0;
		
		try {			
			ret = Integer.parseInt(value);
		} catch (NumberFormatException e ){
			ret = errRet;
		}
		
		return ret;		
	}

	/***
	 * isNumber
	 * @param data
	 * @return
	 */
	public static boolean isNumber(String data){
		Pattern p = Pattern.compile("[0-9.-+]"); 
		Matcher m = p.matcher(data); 
		boolean b = m.matches();
		
		return b;
	}
	
	/***
	 * Parse getParseData rcvBuf as long as nMens length(getParseData rcvBuf를 nLens길이만큼 Parse)
	 * @param nlens
	 * @param strHeaders
	 * @param rcvBuf
	 * @return
	 */
	public static HashMap getParseData(int nlens[], String strHeaders[], String rcvBuf) {		
		int bInx=0;
		int eInx=0;	
		HashMap hm = new HashMap();
		
		eInx = nlens[0];
		for(int i=0; i<nlens.length; i++ ){
			
			hm.put(strHeaders[i].toString(), rcvBuf.substring(bInx, eInx));	
		logger.info( strHeaders[i].toString() + "==>(" + bInx +","+ eInx + ")" + rcvBuf.substring(bInx, eInx));	
			if (i<nlens.length-1){
				bInx = eInx;
				eInx = eInx+nlens[i+1];
			}
		}
		return hm;
	}	
	
	
	/***
	 * Parse getParseDataMultibyte rcvBuf as long as nMens length(getParseDataMultibyte rcvBuf를 멀티바이트 감안해 nLens길이만큼 Parse)
	 * @param nlens
	 * @param strHeaders
	 * @param rcvBuf
	 * @return
	 */
	public static HashMap getParseDataMultibyte(int nlens[], String strHeaders[], String rcvBuf) {		
		int bInx=0;
		int eInx=0;	
		HashMap hm = new HashMap();
		
		eInx = nlens[0];
		for(int i=0; i<nlens.length; i++ ){
			
			hm.put(strHeaders[i].toString(), new String(rcvBuf.getBytes(), bInx, eInx - bInx));	
			logger.info( strHeaders[i].toString() + "==>(" + bInx +","+ eInx + ")" + new String(rcvBuf.getBytes(), bInx, eInx - bInx));	
			if (i<nlens.length-1){
				bInx = eInx;
				eInx = eInx+nlens[i+1];
			}
		}
		return hm;
	}
	
	/***
	 * Parse getParseDataMultibyte rcvBuf as long as nMens length(getParseDataMultibyte rcvBuf를 멀티바이트 감안해 nLens길이만큼 Parse)
	 * @param nlens
	 * @param strHeaders
	 * @param rcvBuf
	 * @return
	 * @throws Exception
	 */
	public static String getConvertUTF16LE2UTF8(String strOrg) throws Exception {		
		byte[] byteOrg = strOrg.getBytes();
		InputStream is = new ByteArrayInputStream( byteOrg );
	    InputStreamReader isr = new InputStreamReader( is, Charset.forName("UTF-16LE") );
	    BufferedReader br = new BufferedReader( isr );
	    String strConv = br.readLine();

	    return strConv;
	}
	
	/***
	 * Parse getParseDataMultibyte rcvBuf as long as nMens length(getParseDataMultibyte rcvBuf를 멀티바이트 감안해 nLens길이만큼 Parse)
	 * @param nlens
	 * @param strHeaders
	 * @param rcvBuf
	 * @return
	 */
	public static HashMap getParseDataMultibyte2(int nlens[], String strHeaders[], String rcvBuf) {		
		int bInx=0;
		int eInx=0;	
		HashMap hm = new HashMap();
		
		eInx = nlens[0];
		for(int i=0; i<nlens.length; i++ ){
			
			hm.put(strHeaders[i].toString(), subStringMultibyte(rcvBuf, bInx, eInx, '+'));	
			//hm.put(strHeaders[i].toString(), rcvBuf.substring(bInx, eInx));	
		logger.info( strHeaders[i].toString() + "==>" + subStringMultibyte(rcvBuf, bInx, eInx, '+'));	
			if (i<nlens.length-1){
				bInx = eInx;
				eInx = eInx+nlens[i+1];
			}
		}
		return hm;
	}	
	
	
	/***
	 * Parse subStringMultibyte rcvBuf as long as nMens length(subStringMultibyte 멀티바이트를 감안해 시작위치, 끝위치 길이만큼 Parse)
	 * @param str
	 * @param bInx
	 * @param eInx
	 * @param type ('+' or '-')
	 * @return
	 */
	public static String subStringMultibyte(String str, int bInx, int eInx ,char type) {
		byte[] bytes = str.getBytes();
		int len = bytes.length;
		int length = eInx - bInx;
		int counter = 0;
		// 자를 길이가 시작위치보다 작으면 뒤에 스페이스를 붙여서 리턴
//		if (length >= len) {
//			StringBuffer sb = new StringBuffer();
//			sb.append(str);
//		
//			for(int i=0;i<length-len;i++){
//				sb.append(' ');
//			}
//			return sb.toString();
//		}

		for (int i = length - 1; i >= bInx; i--) {
			if (((int)bytes[i] & 0x80) != 0)
				counter++;
		}
		String f_str = null;
		if(type == '+'){
			f_str = new String(bytes, bInx, length + (counter % 2));
		}else if(type == '-'){
			f_str = new String(bytes, bInx, length - (counter % 2));
		}else{
			f_str = new String(bytes, bInx, length - (counter % 2));
		}
	
		return f_str;
	}
	
	
	/***
	 * Making makeSendData Response Message Header Data (makeSendData 응답 전문헤더데이타 작성하기) 
	 * @param hm Message Data(전문 데이타) 
	 * @param cmLens Message Length(전문길이) 
	 * @param ret Response Value(응답값) 
	 * @return String Message Data(전문데이타)
	 * 공통 전문 헤더 변경 SPC 용  2016.05 ( 50 BYTE -->64 BYTE
	 */
	public static String makeSendData(HashMap hmCommon, int cmLens, int ret){
		StringBuffer sb = new StringBuffer();
		int nlens[]= {6,2,4,4,10,8,2,5,5,8,6,1,3};  
 
		String strHeaders[] = {
				"MSG_LEN",  	
				"MSG_TYPE",
				"CMP_CD",
				"BRAND_CD",
				"STOR_CD",
				"SALE_DT",
				"POS_NO",
				"REG_NO",
				"TRADE_NO", 
				"SYS_YMD",
				"SYS_HMS",
				"ENCRYT_MODE",
				"ERR_CD" 
			};	 
		
		hmCommon.put("MSG_LEN", StringUtil.lPad(String.valueOf(cmLens),6,"0")) ;
		hmCommon.put("SYS_YMD", (new SimpleDateFormat("yyyyMMdd")).format( new Date() )) ;
		hmCommon.put("SYS_HMS", (new SimpleDateFormat("HHmmss")).format( new Date() )) ;
		hmCommon.put("ERR_CD",   StringUtil.lPad(String.valueOf(ret),3,"0")) ;	
		
		for (int i=0; i < nlens.length ; i++) {
			StringUtil.appendSpace(sb, (String)hmCommon.get(strHeaders[i].toString()), nlens[i]);   
		}

	    //sb.append("\n");
		//sb.append("\r\n");
		return sb.toString();
	}
	
	/***
	 * Making makeSendData Response Message Header Data (makeSendData 응답 전문헤더데이타 작성하기) 
	 * @param hm Message Data(전문 데이타) 
	 * @param cmLens Message Length(전문길이) 
	 * @param ret Response Value(응답값) 
	 * @return String Message Data(전문데이타)
	 */
	public static String makeTMoneySendData(HashMap hmCommon, int cmLens){
		StringBuffer sb = new StringBuffer();
		int nlens[]= {4,3,8,4,1
					 ,1,8,3};  
		
		String strHeaders[] = {
				"TLGM_LEN",
				"WORK_CD",
				"COMPANY_CD",
				"TLGM_CD",
				"DEAL_TP",
					
				"SNDRCV_FG",
				"FILE_NM",
				"RES_CD"
			};	 
		
		hmCommon.put("TLGM_LEN", StringUtil.lPad(String.valueOf(cmLens),4,"0")) ;
		
		for (int i=0; i < nlens.length ; i++) {
			StringUtil.appendSpace(sb, (String)hmCommon.get(strHeaders[i].toString()), nlens[i]);   
		}

	    //sb.append("\n");
		//sb.append("\r\n");
		return sb.toString();
	}
	
	public static String makeHanPaySendData(HashMap<String, String> hmCommon, int cmLens) {
		StringBuffer sb = new StringBuffer();
		int nlens[] = {4,3,4,4,1
				 	  ,1,3};
		
		String strHeaders[] = {
				"TLGM_LEN",
				"WORK_CD",
				"COMPANY_CD",
				"TLGM_CD",
				"DEAL_TP",
					
				"SNDRCV_FG",
				"RES_CD"
		};
		
		hmCommon.put("TLGM_LEN", StringUtil.lPad(String.valueOf(cmLens),4,"0")) ;
		
		for (int i=0; i < nlens.length ; i++) {
			StringUtil.appendSpace(sb, (String)hmCommon.get(strHeaders[i].toString()), nlens[i]);   
		}
		
		return sb.toString();
	}
	
	public static String makeRailPlusSendData(HashMap<String, String> hmCommon, int cmLens) {
		StringBuffer sb = new StringBuffer();
		int nlens[] = {4,3,4,4,1
				 	  ,1,3};
		
		String strHeaders[] = {
				"TLGM_LEN",
				"WORK_CD",
				"COMPANY_CD",
				"TLGM_CD",
				"DEAL_TP",
					
				"SNDRCV_FG",
				"RES_CD"
		};
		
		hmCommon.put("TLGM_LEN", StringUtil.lPad(String.valueOf(cmLens),4,"0")) ;
		
		for (int i=0; i < nlens.length ; i++) {
			StringUtil.appendSpace(sb, (String)hmCommon.get(strHeaders[i].toString()), nlens[i]);   
		}
		
		return sb.toString();
	}

	public static String makeCashBeeSendData(HashMap hmCommon, int cmLens){
		StringBuffer sb = new StringBuffer();
		int nlens[]= {4,3,4,4,1
					 ,1,3};  
		
		String strHeaders[] = {
				"TLGM_LEN",
				"WORK_CD",
				"COMPANY_CD",
				"TLGM_CD",
				"DEAL_TP",
					
				"SNDRCV_FG",
				"RES_CD"
			};	 
		
		hmCommon.put("TLGM_LEN", StringUtil.lPad(String.valueOf(cmLens),4,"0")) ;
		
		for (int i=0; i < nlens.length ; i++) {
			StringUtil.appendSpace(sb, (String)hmCommon.get(strHeaders[i].toString()), nlens[i]);   
		}

	    //sb.append("\n");
		//sb.append("\r\n");
		return sb.toString();
	}

	/***
	 * Parse : Json 문자열을 입력 받아서 hashmap 으로 parsing
	 * @param rcvBuf
	 * @return Hashmap 
	 */
	public static HashMap  jSonParsing(String sjson) { 		
		 
			JsonObject obj =(JsonObject) new com.google.gson.JsonParser().parse(sjson);
			//new JsonParser().parse(sjson).getAsJsonObject(); //
			Iterator i = obj.entrySet().iterator();
			
			HashMap map = new HashMap();
			while (i.hasNext()) {				 			
			    Map.Entry e = (Map.Entry)i.next(); 
			    map.put((String)e.getKey(), e.getValue() );
			 }
		    return map;	
	}
	/***
	 * Make String Data : hashmap 데이터를 String 으로 생성
	 * @param  Hashmap
	 * @return String 
	 */

	public static HashMap  jSonParsing2(String json) {
		 
	    JsonObject object = (JsonObject) new com.google.gson.JsonParser().parse(json);
	    
	    Set<Map.Entry<String, JsonElement>> set = object.entrySet();
	    Iterator<Map.Entry<String, JsonElement>> iterator = set.iterator();
	    HashMap<String, Object> map = new HashMap<String, Object>();
	    while (iterator.hasNext()) {
	        Map.Entry<String, JsonElement> entry = iterator.next();
	        String key = entry.getKey();
	        JsonElement value = entry.getValue();
	        if (!value.isJsonPrimitive()) {
	            map.put(key, jSonParsing2(value.toString()));
	        }else if (value.isJsonArray() ) {
	        	//map.put(key,value.getAsJsonArray());
	        }
	        else {
	            map.put(key, value.getAsString());
	        }
	    }
	    return map;
	}
	
	
	public static String makeMapToSendData(HashMap hmData) {
 
		Gson gson = new GsonBuilder().serializeNulls().create();
		String sb = gson.toJson(hmData);
		return sb.toString();
	}
	
	
}

