package com.eactive.eai.rms.common.util;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.eactive.eai.common.util.StringUtil;

/**
 * <pre>
 * 1.기능 : ITSM SMS 전송을 하기 위한 클래스.
 * 2.처리 개요
 *     - 휴대폰 및 전송 메시지를 입력 받는다.
 *     - ITSM SMS 전송 레이아웃에 맞는 데이터로 변환
 *     - 시스템 설정값에 있는 IP, PORT 로 전송 [IP: "ItsmPermIP", PORT: "ItsmPermPORT"]
 * 3.주의사항 
 *     -
 * </pre>
 * @author JaehyunJu, 2011. 03. 11
 * @version v1.0.0
 * @since JDK v1.5
 */
public class ItsmSmsSender {
	private static Logger logger = Logger.getLogger(ItsmSmsSender.class);
	
	private static int TIME_OUT = 3000; 	// SMS 전송 타임아웃 (MS)

	private static String SMS_MODE = "INFO"; 	// SMS 발송요청구분
	private static int REQ_EMP_MODE = 1; 	// 요청구분자, 1: 직원번호
	private static int REQ_TEL_MODE = 2; 	// 요청구분자, 2: 전화번호
	private static int REQ_GRP_MODE = 3; 	// 요청구분자, 3: 담당자그룹
	private static String DELIMITER = " "; 			// 구분자
	private static String CHK_LIST_DELIMITER = "$";	// 체크리스트용 구분자
	private static String APP_CODE = "EAI";	// 어플리케이션 코드
	private static String REQ_KEY = "NA";	// 어플리케이션 코드
	private static String PRG_NAME = "EAI";	// 프로그램명

	public static String MCI_GRP_MODE = "MCI"; 	// 요청구분자가 "담당자그룹" 일 경우 보낼 그룹
												// (MCI일 경우)
	public static String EAI_GRP_MODE = "EAI"; 	// 요청구분자가 "담당자그룹" 일 경우 보낼 그룹
												// (EAI일 경우)

	/**
	 * <pre>
	 * 1.기능 : 그룹정보를 이용하여 SMS를 전송한다..
	 * 2.사전준비: 전송 IP 및 PORT 설정을 시스템 프로퍼트에 해 주어야 함
	 *     - 방법1: java 실행 시 " -DItsmPermIP=아이피 -DItsmPermPORT=포트 " 를 추가
	 *     - 방법2: System.setProperty("ItsmPermIP", "아이피"); System.setProperty("ItsmPermPORT", "포트"); 입력
	 * 3. 사용법
	 *     - ItsmSmsSender.sendGroup(ItsmSmsSender.MCI_GRP_MODE, "그룹정보", "SMS 메시지"); * SMS 메시지는 76바이트로 제한됨
	 * </pre>
	 * @param sendGrp : 발송요청구분 (MCI: ItsmSmsSender.MCI_GRP_MODE, EAI: ItsmSmsSender.EAI_GRP_MODE)
	 * @param group : 발송그룹정보 (MCI: ItsmSmsSender.MCI_GRP_MODE, EAI: ItsmSmsSender.EAI_GRP_MODE)
	 * @param msg 	: SMS 메시지
	 * @author JaehyunJu, 2011. 03. 14
	 */
	public static boolean sendGroupSMS(Map<String,String> info,String sendGrp, String group, String msg) {
		return sendSMS(info, sendGrp, REQ_GRP_MODE, group, msg, "S");
	}
	public static boolean sendGroupPUSH(Map<String,String> info,String sendGrp, String group, String msg) {
		return sendSMS(info, sendGrp, REQ_GRP_MODE, group, msg, "P");
	}

	/**
	 * <pre>
	 * 1.기능 : 전화번호를 이용하여 SMS를 전송한다..
	 * 2.사전준비: 전송 IP 및 PORT 설정을 시스템 프로퍼트에 해 주어야 함
	 *     - 방법1: java 실행 시 " -DItsmPermIP=아이피 -DItsmPermPORT=포트 " 를 추가
	 *     - 방법2: System.setProperty("ItsmPermIP", "아이피"); System.setProperty("ItsmPermPORT", "포트"); 입력
	 * 3. 사용법
	 *     - ItsmSmsSender.sendPhone(ItsmSmsSender.MCI_GRP_MODE, "휴대폰번호", "SMS 메시지"); * SMS 메시지는 76바이트로 제한됨
	 * </pre>
	 * @param sendGrp : 발송요청구분 (MCI: ItsmSmsSender.MCI_GRP_MODE, EAI: ItsmSmsSender.EAI_GRP_MODE)
	 * @param phone : 휴대폰번호
	 * @param msg 	: SMS 메시지
	 * @author JaehyunJu, 2011. 03. 14
	 */
	public static boolean sendPhoneSMS(Map<String,String> info,String sendGrp, String phone, String msg) {
		return sendSMS(null, sendGrp, REQ_TEL_MODE, phone, msg, "S");
	}
	public static boolean sendPhonePUSH(Map<String,String> info, String sendGrp, String phone, String msg) {
		return sendSMS(info, sendGrp, REQ_TEL_MODE, phone, msg, "P");
	}

	/**
	 * <pre>
	 * 1.기능 : 직원번호를 이용하여 SMS를 전송한다..
	 * 2.사전준비: 전송 IP 및 PORT 설정을 시스템 프로퍼트에 해 주어야 함
	 *     - 방법1: java 실행 시 " -DItsmPermIP=아이피 -DItsmPermPORT=포트 " 를 추가
	 *     - 방법2: System.setProperty("ItsmPermIP", "아이피"); System.setProperty("ItsmPermPORT", "포트"); 입력
	 * 3. 사용법
	 *     - ItsmSmsSender.sendEmp(ItsmSmsSender.MCI_GRP_MODE, "직원번호", "SMS 메시지"); * SMS 메시지는 76바이트로 제한됨
	 * </pre>
	 * @param sendGrp : 발송요청구분 (MCI: ItsmSmsSender.MCI_GRP_MODE, EAI: ItsmSmsSender.EAI_GRP_MODE)
	 * @param empno : 직원번호
	 * @param msg : SMS 메시지
	 * @author JaehyunJu, 2011. 03. 14
	 */
	public static boolean sendEmpSMS(Map<String,String> info,String sendGrp, String empno, String msg) {
		return sendSMS(info,sendGrp, REQ_EMP_MODE, empno, msg, "S");
	}
	public static boolean sendEmpPUSH(Map<String,String> info,String sendGrp, String empno, String msg) {
		return sendSMS(info, sendGrp, REQ_EMP_MODE, empno, msg, "P");
	}

	// 메시지 조립
	private static boolean sendSMS(Map<String,String> info, String sendGrp, int mode, String data, String msg, String sendType) {
		if (msg == null ) {
			printLog("전송 메시지가 존재하지 않습니다.!!");
			return false;
		}
		//PUSH 일 때도 80Byte 제한 해줘야 함( PUSH를 못받는 상황에서는 알림이 SMS로 변경되어서 나가기 때문에 길이제한을 둠 )
		if (msg.getBytes().length > 76) {
			String msg2 = StringUtil.chunkString(msg, 76, false);
			printLog("전송 메시지가 76 byte를 넘었습니다. 메시지=[" + msg + "] 는 ["+ msg2 +"]로 변경됨.!!");
			msg = msg2;
		}
		
		String ip   = null;
		String port = null;
		if (info == null){
			printLog("아이피 또는 포트정보가 유효하지 않습니다.");
			return false;
		}
		ip   = (String)info.get("ItsmPermIP");
		port = (String)info.get("ItsmPermPORT");
		
		if (ip == null || ip.trim().length() == 0 || port == null || port.trim().length() == 0) {
			printLog("아이피 또는 포트정보가 유효하지 않습니다.");
			return false;
		}
		/* SMS_MODE 		전송구분	> INFO
		 * mode 			요청구분자	> 1(직원번호),2(전화번호),3(수신APP코드그룹)
		 * sendGrp			수신대상자(발송대상자키)	> S010794(1), 01000000000(2), EAI(3)
		 * getDateTime()	이벤트발생시간
		 * data				요청자
		 * sendType			발송대상 타입 > S단문 L장문 M메신저 V음성경보 P푸시
		 * apCode			어플리케이션코드  > EAI
		 * prgName			프로그램명 	ex) EAI CM적용에러	//딱히 적을 내용이없어서 현재  EAI로 정의해놓음 
		 * reqKey			요청구분키	ex) cm패키지명 등? 없으면 NA 
		 * msg				메시지
		 */
		
		String packet = SMS_MODE + DELIMITER + mode + DELIMITER + sendGrp + DELIMITER + getDateTime() + DELIMITER + data + DELIMITER 
				+ sendType + DELIMITER + APP_CODE + DELIMITER + PRG_NAME + DELIMITER + REQ_KEY + DELIMITER + msg;
		
		sendMessage(ip, port, packet);
		
		return true;
	}

	// SMS 데이터 전송
	private static void sendMessage(String ip, String port, String packet) {
		Socket s = null;
		DataOutputStream out = null;
		InetSocketAddress saddr = null;

		byte bMsg[] = null;

		printLog(ip + ":" + port + " Connection 시도!!");

		try {
			saddr = new InetSocketAddress(ip, Integer.parseInt(port));
			s = new Socket();
			s.setSoTimeout(TIME_OUT); // MS 타임아웃 시간 설정
			s.connect(saddr, TIME_OUT);

			// DataStream과 Socket 연결
			out = new DataOutputStream(new BufferedOutputStream(s.getOutputStream()));
			bMsg = packet.getBytes();

			printLog("전송 메시지=[" + packet + "]");

			// 메시지 전송
			out.write(bMsg);
			out.flush();
		} catch (Exception e) {
			printLog("SMS 메시지 전송 중 에러발생!!, IP=[" + ip + "], PORT=[" + port + "], 타임아웃=[" + TIME_OUT + "], 메시지=[" + packet + "]");
		} finally {
			if (out != null)
				try {
					out.close();
				} catch (Exception e) {}
			if (s != null)
				try {
					s.close();
				} catch (Exception e) {}
		}
	}

	// 시간함수 (년월일시분초)
	private static String getDateTime() {
		return CommonUtil.getCurrentDateTime();
	}

	// 로그출력
	private static void printLog(String msg) {
		logger.info("[ITSM-SMS] " + msg);
	}

	/**
	 * <pre>
	 * 1.기능 : ITSM에 체크리스트를 전송한다..
	 * 2.사전준비: 전송 IP 및 PORT 설정을 시스템 프로퍼트에 해 주어야 함
	 *     - 방법1: java 실행 시 " -DItsmCheckListIP=아이피 -DItsmCheckListPORT=포트 " 를 추가
	 *     - 방법2: System.setProperty("ItsmCheckListIP", "아이피"); System.setProperty("ItsmCheckListPORT", "포트"); 입력
	 * </pre>
	 * @param sendNum		: 업무일련번호
	 * @param resultVal		: 점검결과값
	 * @param systemName	: 대상시스템명
	 * @param detailMsg		: 비고(상세내용)
	 * @참고사항 실 전문에는 정상유무 항목이 있으나, EAI에서는 사용하지 않는 항목이므로 DELIMITER 두개를 연속해서 사용
	 * @author  KSH, 2016. 08. 11
	 */
	public static boolean sendCheckList(String sendNum, String resultVal, String systemName, String detailMsg) {
		if (StringUtils.isEmpty(System.getProperty("ItsmCheckListIP")) || StringUtils.isEmpty(System.getProperty("ItsmCheckListPORT"))) {
			printLog("아이피 또는 포트정보가 유효하지 않습니다.");
			return false;
		}
		return sendCheckListMsg(sendNum, resultVal, systemName, detailMsg);
	}
	
	// 체크리스트용 메시지 조립
	private static boolean sendCheckListMsg(String sendNum, String resultVal, String systemName, String detailMsg) {
		String checkListIp = System.getProperty("ItsmCheckListIP");
		String checkListPort = System.getProperty("ItsmCheckListPORT");
		if (checkListIp == null || checkListIp.trim().length() == 0 || checkListPort == null || checkListPort.trim().length() == 0) {
			printLog("아이피 또는 포트정보가 유효하지 않습니다. IP=["+ checkListIp +"], PORT=["+ checkListPort +"]");
			return false;
		}
		//전송년월일시(yyyymmddhhmmss) + 업무대분류(MEK) + 업무중분류(EAI) + 업무일련번호 + 점검결과값 + 정상여부(EAI사용안함) + 점검시스템명
		String 	packet 	= getDateTime() + CHK_LIST_DELIMITER + "MEK" + CHK_LIST_DELIMITER + "EAI" + CHK_LIST_DELIMITER + sendNum + CHK_LIST_DELIMITER + resultVal + CHK_LIST_DELIMITER + CHK_LIST_DELIMITER + systemName + CHK_LIST_DELIMITER + detailMsg;
		sendMessage(checkListIp, checkListPort, packet);
		return true;
	}
	
//	private static void setCheckListInfo() {
//		try {
//			DAOFactory factory = DAOFactory.newInstance();
//			PropertyDAO inboundErrorInfoDao = (PropertyDAO)factory.create(PropertyDAO.class);
//			PropGroupVO vo = inboundErrorInfoDao.getProperties("ITSM_SMS");
//			String itsmCheckListIp = vo.getProperty("ItsmCheckListIP");
//			if (!StringUtils.isEmpty(itsmCheckListIp)) {
//				System.setProperty("ItsmCheckListIP", itsmCheckListIp);
//			}
//			String itsmCheckListPort = vo.getProperty("ItsmCheckListPORT");
//			if (!StringUtils.isEmpty(itsmCheckListPort)) {
//				System.setProperty("ItsmCheckListPORT", itsmCheckListPort);
//			}
//			String axwayIp = vo.getProperty("AxwayIP");
//			if (!StringUtils.isEmpty(axwayIp)) {
//				System.setProperty("AxwayIP", axwayIp);
//			}
//			String axwayPort = vo.getProperty("AxwayPORT");
//			if (!StringUtils.isEmpty(axwayPort)) {
//				System.setProperty("AxwayPORT", vo.getProperty("AxwayPORT"));
//			}
//		} catch (DAOException e) {
//			printLog(e.toString());
//		}
//	}
	
	//에러건수 SMS발송  
	public static boolean errorSendSMS(String division,int mode,String sendGroup, String sendTime , String empno,String sendType,String appCd,String prgName , String reqFlag , String detailMsg) {
		return sendTranErrorMsg(division,mode,sendGroup, sendTime ,empno, sendType,appCd, prgName, reqFlag , detailMsg);
	}
	
	//에러건수 SMS발송 메시지 조립
	private static boolean sendTranErrorMsg(String division,int mode,String sendGroup, String sendTime , String empno,String sendType,String appCd,String prgName , String reqFlag, String detailMsg) {
		boolean result = true;
		
		String itsmPermIP = System.getProperty("ItsmPermIP");
		String itsmPermPORT = System.getProperty("ItsmPermPORT");
		if (itsmPermIP == null || itsmPermIP.trim().length() == 0 || itsmPermPORT == null || itsmPermPORT.trim().length() == 0) {
			printLog("아이피 또는 포트정보가 유효하지 않습니다. IP=["+ itsmPermIP +"], PORT=["+ itsmPermPORT +"]");
			result =  false;
		}
		
		
		//INFO 3 EAI 20200513115111 1562325 P EAI EAI발송프로그램이름 NA 발송메시지
		String 	packet 	= division + DELIMITER + mode + DELIMITER + sendGroup + DELIMITER + sendTime + DELIMITER + empno + DELIMITER +sendType + DELIMITER + appCd + DELIMITER +  prgName +  DELIMITER + reqFlag + DELIMITER + detailMsg;
		result = sendErrorMessage(itsmPermIP, itsmPermPORT, packet);
		return result;
	}
	
	// SMS 데이터 전송
	private static boolean sendErrorMessage(String ip, String port, String packet) {
		Socket s = null;
		DataOutputStream out = null;
		InetSocketAddress saddr = null;

		byte bMsg[] = null;

		printLog(ip + ":" + port + " Connection 시도!!");

		try {
			saddr = new InetSocketAddress(ip, Integer.parseInt(port));
			s = new Socket();
			s.setSoTimeout(TIME_OUT); // 3000 > 6000 수정반영
			s.connect(saddr, TIME_OUT);

			// DataStream과 Socket 연결
			out = new DataOutputStream(new BufferedOutputStream(s.getOutputStream()));
			bMsg = packet.getBytes();

			printLog("전송 메시지=[" + packet + "]");

			// 메시지 전송
			out.write(bMsg);
			out.flush();
		} catch (Exception e) {
			printLog("SMS 에러메시지 전송 중 에러발생!!, IP=[" + ip + "], PORT=[" + port + "], 타임아웃=[" + TIME_OUT + "], 메시지=[" + packet + "]" );
			logger.error("SMS sendMessage error : " + e.getMessage());
			return false;
		} finally {
			if (out != null)
				try {
					out.close();
				} catch (Exception e) {}
			if (s != null)
				try {
					s.close();
				} catch (Exception e) {}
		}
		return true;
	}
//	public static void main(String[] args) {
//		HashMap<String, String> m = new HashMap();
//		String t = "테스트테스트테스트테스트테스트";
//		m.put("ItsmPermIP", "10.38.116.111");
//		m.put("ItsmPermPORT", "3264");
//		sendSMS(m, "S010794", REQ_EMP_MODE, "S010794", t, "P");
//	}
	
}
