package com.eactive.eai.rms.onl.manage;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import com.eactive.eai.rms.common.base.BaseService;
import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.login.SessionManager;
import com.eactive.eai.rms.common.spring.BaseController;
import com.eactive.eai.rms.common.util.StringUtils;
import com.eactive.eai.rms.onl.manage.rule.layoutsync.LayoutSyncService;
import com.eactive.eai.rms.onl.manage.rule.transform.TransformManService;
import com.eactive.eai.rms.onl.manage.rule.transform.TransformMappingManService;
import com.eactive.eai.rms.onl.manage.serviceinfo.eaimsg.EaiMsgManService;
import com.eactive.eai.rms.onl.manage.serviceinfo.stdmessage.StdMessageManService;
import com.eactive.eai.rms.onl.transaction.extnl.InterfaceManService;


@Aspect
@Component
public class LayoutMappingInfoAspect extends BaseController {

	@Autowired
	ApplicationContext appCoxt;

	@Autowired
	LayoutSyncService service;

	@Autowired
	MonitoringContext monitoringContext;

	@Pointcut("(execution(* com.eactive.eai.rms.onl.manage.rule.transform.TransformManService.transaction(..))"
			+ "|| execution(* com.eactive.eai.rms.onl.manage.rule.transform.TransformManService.delete(..))"
			+ "|| execution(* com.eactive.eai.rms.onl.manage.rule.transform.TransformMappingManService.*RefMsgID(..))"
			+ "|| execution(* com.eactive.eai.rms.onl.manage.serviceinfo.stdmessage.StdMessageManService+.clone(..))"
			+ "|| execution(* com.eactive.eai.rms.onl.manage.serviceinfo.stdmessage.StdMessageManService+.insert(..))"
			+ "|| execution(* com.eactive.eai.rms.onl.manage.serviceinfo.stdmessage.StdMessageManService+.delete(..))"
			+ "|| execution(* com.eactive.eai.rms.onl.manage.serviceinfo.stdmessage.StdMessageManService+.update(..))"
			+ "|| execution(* com.eactive.eai.rms.onl.manage.serviceinfo.eaimsg.EaiMsgManService.insertSvc(..))"
			+ "|| execution(* com.eactive.eai.rms.onl.manage.serviceinfo.eaimsg.EaiMsgManService.updateSvc(..))"
			+ "|| execution(* com.eactive.eai.rms.onl.manage.serviceinfo.eaimsg.EaiMsgManService.deleteSvc(..))"
			+ "|| execution(* com.eactive.eai.rms.onl.transaction.extnl.InterfaceManService.insert(..))"
			+ "|| execution(* com.eactive.eai.rms.onl.transaction.extnl.InterfaceManService.update(..))"
			+ "|| execution(* com.eactive.eai.rms.onl.transaction.extnl.InterfaceManService.delete(..))"
			+ ") && args(obj, ..)")
	public void mapping(Object obj) {
	}

	@Around(value = "com.eactive.eai.rms.onl.manage.LayoutMappingInfoAspect.mapping(obj)")
	public Object aroundMapping(ProceedingJoinPoint thisJoinPoint, Object obj) throws Throwable {

    	final MethodSignature signature = (MethodSignature)thisJoinPoint.getSignature();
    	final String[] parameterNames = signature.getParameterNames();
    	final Object[] parameterValues = thisJoinPoint.getArgs();
    	for(String parameterName : parameterNames){
    		logger.debug("LayoutMappingInfoAspect] parameterName="+parameterName);
    	}
    	/**
    	 * .aj 에서 @Aspect 로 변경시 문제점 발견
    	 * 1. aj 에서 는 parameter가 같을경우에만 실행 되고 @Aspect 는 순서와 타입만 맞으면 실행되는 문제 발생 (실행되지 말아야 할께 실행되는문제)
    	 * 해결책) 맞는 paramter와 값을 셋팅해서 쓴다.(현재 LayoutMappingInfoAspect는 obj라는 paramter를 쓰는데가 없음)
    	 *   1. obj 란 parameter가 없을경우 proceed를 실행하고 빠져나간다.
    	 *   2. obj 에 정확한 값을 셋팅한다.
    	 */
    	boolean existObj = false;
    	for(int i=0;i<parameterNames.length;i++){
    		String parameterName = parameterNames[i];
    		if ("obj".equals(parameterName)){
    			existObj = true;
    			obj = (Object)parameterValues[i];
    		}
    	}
    	if (!existObj){
			try {
				return thisJoinPoint.proceed(parameterValues);
			} catch (Throwable e) {
				throw e;
			}
    	}
    	
    	logger.debug("LayoutMappingInfoAspect] obj="+obj);
		
		if (thisJoinPoint.getThis() instanceof BaseService) {
		} else if (thisJoinPoint.getThis() instanceof BaseController) {
		} else {
			try {
				return thisJoinPoint.proceed(parameterValues);
			} catch (Throwable e) {
				throw e;
			}
		}

		// 1. parameter 설정
		List<HashMap<String, String>> paramList = new ArrayList<HashMap<String, String>>();

		HashMap<String, String> param = new HashMap<String, String>();
		param.put("schema", DataSourceContextHolder.getDataSourceType().getName());
		String eaiSvcName = null;
		String cmd = null;

		// 2. eaiSvcName, cmd 설정
		if (thisJoinPoint.getThis() instanceof TransformManService) {
			// method key,value
			String[] paramNames = ((CodeSignature) thisJoinPoint.getStaticPart().getSignature()).getParameterNames();
			Object[] args = thisJoinPoint.getArgs();
			HashMap<String, Object> h = new HashMap<String, Object>();
			for (int i = 0; i < paramNames.length; i++) {
				h.put(paramNames[i], args[i]);
			}

			cmd = thisJoinPoint.getSignature().getName().startsWith("delete") ? "delete" : "insert";

			param.put("eaiSvcName", StringUtils.defaultString((String) h.get("eaiSvcName"), ""));
			param.put("cmd", StringUtils.defaultString(cmd, ""));
			paramList.add(param);
		} else if (thisJoinPoint.getThis() instanceof TransformMappingManService) {
			Object[] args = thisJoinPoint.getArgs();
			HashMap<String, Object> vo = null;
			for (int i = 0; i < args.length; i++) {
				if (args[i] instanceof HashMap) {
					vo = (HashMap<String, Object>) args[i];
					break;
				}
			}
			cmd = thisJoinPoint.getSignature().getName().startsWith("delete") ? "delete" : "insert";

			param.put("eaiSvcName", StringUtils.defaultString((String) vo.get("eaiSvcName"), ""));
			param.put("cmd", StringUtils.defaultString(cmd, ""));
			paramList.add(param);

		} else if (thisJoinPoint.getThis() instanceof EaiMsgManService) {
			if (obj instanceof HashMap) {
				HashMap<String, Object> vo = (HashMap<String, Object>) obj;
				eaiSvcName = (String) vo.get("eaiSvcName");
			}
			// 복제 여부 확인 해야됨
			cmd = thisJoinPoint.getSignature().getName().startsWith("delete") ? "delete" : "insert";
			param.put("eaiSvcName", StringUtils.defaultString(eaiSvcName, ""));
			param.put("cmd", StringUtils.defaultString(cmd, ""));
			paramList.add(param);
		} else if (thisJoinPoint.getThis() instanceof InterfaceManService) {
			if (obj instanceof HashMap) {
				HashMap<String, Object> vo = (HashMap<String, Object>) obj;
				eaiSvcName = (String) vo.get("eaiSvcName");
			}
			cmd = thisJoinPoint.getSignature().getName().startsWith("delete") ? "delete" : "insert";

			param.put("eaiSvcName", StringUtils.defaultString(eaiSvcName, ""));
			param.put("cmd", StringUtils.defaultString(cmd, ""));
			paramList.add(param);
		} else if (thisJoinPoint.getThis() instanceof StdMessageManService) {
			// 내부표준전문 저장시
			if (obj instanceof HashMap) {
				HashMap<String, Object> vo = (HashMap<String, Object>) obj;

				eaiSvcName = (String) vo.get("bzwkSvcKeyName") + (String) vo.get("splizDmndDstcd")
						+ (String) vo.get("stndTelgmWtinExtnlDstcd");
				cmd = thisJoinPoint.getSignature().getName().startsWith("delete") ? "delete" : "insert";

				param.put("eaiSvcName", StringUtils.defaultString(eaiSvcName, ""));
				param.put("cmd", StringUtils.defaultString(cmd, ""));
				paramList.add(param);
			}

		}

		Object rts = null;
		// Property 정보 취득
		Properties prop = new Properties();
		List<HashMap<String, String>> propertyDetail;
		try {
			// List로 구성된 transaction 정보 다중 처리
			for (HashMap<String, String> m : paramList) {
				if (!"".equals(m.get("eaiSvcName")) && !"".equals(m.get("cmd"))) {
					// 3. 서비스 호출
					String serno = UUID.randomUUID().toString();
					String xmlQuery = null;
					// 본거래에 대한 transaction 보장
					try {
						if ("delete".equals(cmd)) {
							xmlQuery = service.getLayoutMappingXMLList(m);
							rts = thisJoinPoint.proceed(parameterValues);
						} else {
							rts = thisJoinPoint.proceed(parameterValues);
							xmlQuery = service.getLayoutMappingXMLList(m);
						}
					} catch (Exception e) {
						logger.error("Exception -" + e.getMessage(), e);
						if (rts == null)
							rts = e.getMessage();
						if (thisJoinPoint.getStaticPart().toString().replace("execution(", "").startsWith("int")) {
							rts = -1;
						}
						throw e;
					} catch (Throwable throwable) {
						throwable.printStackTrace();
					}
					// IIM sync 전송 여부
					String syncYn = monitoringContext.getStringProperty("iim.sync.yn");
					if (!"Y".equals(syncYn)) {
						continue;
					}
					if (xmlQuery.contains("Layout")) {
						HashMap<String, String> map = new HashMap<String, String>();
						map.put("executeClass", thisJoinPoint.getSignature().getDeclaringType().getName());
						map.put("executeMethod", thisJoinPoint.getSignature().getName());
						if (obj instanceof HttpServletRequest) {
							map.put("executeUser", SessionManager.getUserId((HttpServletRequest) obj));
						}
						map.put("logPrcssSerno", StringUtils.rightPad(serno, 40, " "));
						map.put("sendXmlCmnt", xmlQuery);

//    	        		//4. 전송처리
//    	        		try {
//
//    	        			//layout sync 송신로그
//    	        			service.addLayoutMappingSyncLog(map);
//
//    	        			String url = monitoringContext.getStringProperty("iim.layout.mapping");
//    	        			if( url == null ) {
//    	        			    throw new Exception("수신서버의 정보를 찾을 수 없습니다.");
//    	        			}
//
//    		        		String recvMsg = service.syncLayout(url, xmlQuery);
//
//    		        		// 응답전문 성공/실패 처리 확인
//    		        		SAXBuilder builder = new SAXBuilder();
//    		        		org.jdom.Document recv = builder.build( new ByteArrayInputStream(recvMsg.getBytes()) );
//    		        		org.jdom.Element results = recv.getRootElement();
//
//    		        		if( "FALSE".equals(results.getChild("Result").getText().toUpperCase()) ) {
//    			        		map.put("recvRslt", "F");
//    			        		map.put("recvFailCmnt", results.getChild("ResultMessage").getText());
//    		        		} else {
//    			        		map.put("recvRslt", "S");
//    		        		}
//    		        		//layout sync 수신로그
//    		        		service.recvLayoutMappingSyncLog(map);
//    	        		} catch(Exception e) {
//    	        			logger.error ("iim 전송중 오류 " + e.getMessage(),e);
//    		        		map.put("recvRslt", "F");
//    		        		map.put("recvFailCmnt", e.getMessage());
//    	        		}
					} // end if
				} // end if
			} // end for
		} catch (Exception e1) {
			logger.error("Exception : -" + e1.getMessage(), e1);
			if (rts == null)
				rts = e1.getMessage();
			if (thisJoinPoint.getStaticPart().toString().replace("execution(", "").startsWith("int")) {
				rts = -1;
			}
			throw e1;
		}
		return rts;
	}
}
