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

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;

import com.eactive.eai.rms.common.acl.user.RecordAuthUtil;
import com.eactive.eai.rms.common.login.LoginVo;
import com.eactive.eai.rms.common.login.SessionManager;
import com.eactive.eai.rms.common.util.CommonConstants;

public class MonitoringFrontFilter implements Filter {

	/** Logger for this class. */
	private static final Logger logger = Logger.getLogger(MonitoringFrontFilter.class);

	/** The Constant QUEUE. */
	public static final String QUEUE = "com.eactive.eai.rts.bean.OperMgtAccsLogQueue";

	/** The Constant SERVICE_RULE_FILE. */
	public static final String SERVICE_RULE_FILE = "service_rules.xml";

	@Override
	public void init(FilterConfig arg0) throws ServletException {

	}

	@Override
	public void destroy() {

	}

	public boolean isNonFilterRequest(HttpServletRequest request) {

		String uri = request.getRequestURI();

		if(uri.startsWith(request.getContextPath()+"/jsp")) {
			return false;
		}

		if (	uri.equals(request.getContextPath() + "/")
				|| uri.endsWith(".jsp")
				|| uri.endsWith(".png")
				|| uri.endsWith(".jpg")
				|| uri.endsWith(".css")
				|| uri.endsWith(".gif")
				|| uri.endsWith(".ico")
				|| uri.endsWith(".html")
				|| uri.endsWith(".md")
				|| uri.startsWith(request.getContextPath()+"/image")
				|| uri.startsWith(request.getContextPath()+"/images")
				|| uri.startsWith(request.getContextPath()+"/img")
				|| uri.startsWith(request.getContextPath()+"/js")
				|| uri.startsWith(request.getContextPath()+"/addon")
				|| uri.startsWith(request.getContextPath()+"/css")
				|| uri.startsWith(request.getContextPath()+"/theme")
				|| uri.startsWith(request.getContextPath()+"/login")
				|| uri.startsWith(request.getContextPath()+"/theme")
				|| uri.startsWith(request.getContextPath()+"/css")
				|| uri.indexOf(request.getContextPath() +"/LoginServlet") > -1
				|| uri.indexOf(request.getContextPath() +"/login/") > -1
				|| uri.indexOf(request.getContextPath() +"/dashboard") > -1
				|| uri.indexOf(request.getContextPath() +"/dashmain3.do") > -1
				|| uri.indexOf(request.getContextPath() + "/loginForm.do") > -1
				|| uri.indexOf(request.getContextPath() + "/login.do") > -1
				|| uri.indexOf(request.getContextPath() + "/login-ajax.do") > -1
				|| uri.indexOf(request.getContextPath() + "/sms-auth/") > -1
				|| uri.indexOf(request.getContextPath() + "/ssoLogin.do") > -1
				|| uri.indexOf(request.getContextPath() + "/changePassword.do") > -1
				|| uri.indexOf(request.getContextPath() + "/dashboard") > -1
				|| uri.indexOf(request.getContextPath() + "/layoutSync.do") > -1
				|| uri.indexOf(request.getContextPath() + "/layoutSyncB.do") > -1
				|| uri.indexOf(request.getContextPath() + "/loader.do") > -1
				|| uri.indexOf(request.getContextPath() + "/loader.json") > -1
				|| uri.indexOf(request.getContextPath() + "/loaderBAP.do") > -1  //일괄전송
				|| uri.indexOf(request.getContextPath() + "/loaderBAP.json") > -1
				|| uri.indexOf(request.getContextPath() + "/tranblock.do") > -1
				|| uri.indexOf(request.getContextPath() + "/tranblockStatus.do") > -1
				|| uri.indexOf(request.getContextPath() + "/historyList.do") > -1
				|| uri.indexOf(request.getContextPath() + "/adapterStatus.do") > -1 //어댑터 상태 조회
				|| uri.indexOf(request.getContextPath() + "/adapterInstanceRecover.do") > -1 //NODE 장애시 instance 변경후 재기동- Client이고 이중화가 안되어 있는경우
				|| uri.indexOf(request.getContextPath() + "/adapterInstanceChange.do") > -1 //소스적용시  instance 변경후 어댑터기동 이전 instance 어댑터는 중지- Client이고 이중화가 안되어 있는경우
				|| uri.indexOf(request.getContextPath() + "/onl/transaction/tracking/trackingMan.json") > -1 	// 타팀에서 로그정보 조회하기 위함
				|| uri.indexOf(request.getContextPath() + "/adapterChnlLoader.do") > -1	//어댑터채널정보 동기화
				|| uri.indexOf(request.getContextPath() + "/refresh.do" ) >-1	//모니텅링 프로퍼티 재로딩
				|| uri.indexOf(request.getContextPath() + "/schedulerReload.do" ) >-1	//Scheduler Reload 재로딩
				|| uri.indexOf(request.getContextPath() + "/service/tasInfoService.do" ) >-1	//TAS 연동 서비스
				|| uri.indexOf(request.getContextPath() + "/mmiSync.file" ) >-1	//MMI 연동서비스
				|| uri.indexOf(request.getContextPath() + "/mmiSync.do" ) >-1	//MMI 연동서비스
				|| uri.indexOf(request.getContextPath() + "/eimsSync.file" ) >-1	//EIMS 연동서비스
				|| uri.indexOf(request.getContextPath() + "/eimsSync.do" ) >-1	    //EIMS 연동서비스
				|| uri.indexOf(request.getContextPath() + "/cmFileUpload.file" ) >-1	//CM File Upload 연동서비스
				|| uri.indexOf(request.getContextPath() + "/ioMapLoader.do" ) >-1	//CM iomap 연동서비스
				|| uri.indexOf(request.getContextPath() + "/adapterSchedulerReload.do" ) >-1	//adapter Scheduler Reload 재로딩
				|| uri.indexOf(request.getContextPath() + "/detailOsidInstInfo.json" ) >-1	//mci 대외기관정보 조회
				|| uri.indexOf(request.getContextPath() + "/deleteUserAuthforProd.do" ) >-1	//운영 사용자 업무코드 권한 업데이트
				|| uri.indexOf(request.getContextPath() + "/insertUserAuthforProd.do" ) >-1	//운영 사용자 업무코드 권한 업데이트
				|| uri.indexOf(request.getContextPath() + "/eimsbatcall.file" ) >-1	 //EIMS배치 연동서비스
				|| uri.indexOf(request.getContextPath() + "/eimsbapcall.file" ) >-1	 //EIMS일괄 연동서비스
				|| uri.indexOf(request.getContextPath() + "/search.json" ) >-1	 //형상조회
				|| uri.indexOf(request.getContextPath() + "/searchBAP.json" ) >-1	 //형상조회(BAP)
				|| uri.indexOf(request.getContextPath() + "/searchBAT.json" ) >-1	 // 배치 형상조회
				|| uri.indexOf(request.getContextPath() + "/loaderBAT.do" ) >-1	 // 배치 형상 upload/download
				|| uri.indexOf(request.getContextPath() + "/loaderBAT.json" ) >-1	 // 배치 형상 upload/download
				|| uri.indexOf(request.getContextPath() + "/epb/cm.do" ) >-1	 //cm적재
				|| uri.indexOf(request.getContextPath() + "/epb/cm.json" ) >-1	 //cm적재
				|| uri.indexOf(request.getContextPath() + "/epb/cmBAP.do" ) >-1	 //cm적재
				|| uri.indexOf(request.getContextPath() + "/epb/cmBAP.json" ) >-1	 //cm적재
				|| uri.indexOf(request.getContextPath() + "/epb/cmBAT.json" ) >-1	 //cm적재
				|| uri.indexOf(request.getContextPath() + "/document/itsmxml.do" ) >-1	// itsm 통합관제 데이터 제공
				|| uri.indexOf(request.getContextPath() + "/document/itsmjson.do" ) >-1	// itsm 통합관제 데이터 제공
				|| uri.indexOf(request.getContextPath() + "/api/v1/itsm/" ) >-1	// 외부 api제공 *현재 통합관제만 제공으로 제한
            || uri.indexOf(request.getContextPath() + "/adapter/change" ) >-1   // 어댑터 전환관리
            || uri.indexOf(request.getContextPath() + "/deployresource" ) >-1   // 메타데이터 배포
		) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

		HttpServletRequest request = (HttpServletRequest) req;

		if(isNonFilterRequest(request)) {
			chain.doFilter(req, res);
			return;
		}

		try {

			monitoringFrontFilter(req, res, chain);

		} catch (NoClassDefFoundError e) {
			/** IGNORE ERROR **/
			logger.warn("ERROR IGNORE : " + e.getMessage());
		} catch (Exception e) {
			logger.warn(e.getMessage());
			request.setAttribute("errorMessage", e.getMessage());
			throw new ServletException(e);
		}
	}

	private void monitoringFrontFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws Exception {

		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;

		HttpSession cSession = request.getSession();
		String uri = request.getRequestURI();

		if(!loginValidation(uri, cSession, request, response)) {
			return;
		}

		if(!serviceTypeValidation(uri, cSession, request, response)) {
			return;
		}

		String userId = SessionManager.getUserId(request);
      String serviceType = request.getParameter("serviceType");

		if (uri.endsWith(".do")) {

			parameterNamesLogging(req);

			String menuId = req.getParameter("menuId");

			if (menuId != null ? (!"".equals(menuId.trim()) && !menuId.endsWith("000")) : false) { // 탑메뉴 제외하고 메뉴 이동시 권한

            String auth = RecordAuthUtil.getMenuAuth(request, userId, menuId.substring(0, 7), serviceType);

				if (auth == null ? true : auth.equals("")) {
					response.sendRedirect(request.getContextPath()+ "/");
					return;
				}

			}

			chain.doFilter(req, res);

		} else if (uri.endsWith(".json")) {

			parameterNamesLogging(req);

			String cmd = req.getParameter("cmd");
			String viewUrl_fromjsonUrl = uri.substring(0, uri.length() - 5) + ".view";
         String auth = RecordAuthUtil.getMenuUrlAuth(request, userId, viewUrl_fromjsonUrl, serviceType);

			if (authIgnoreCommands(cmd)) {

				chain.doFilter(req, res);
				return;
			}

			if ("W".equals(auth)) {

				chain.doFilter(req, res);
				return;

			} else if ("R".equals(auth) && readAuthIgnoreCommands(cmd)) {

				chain.doFilter(req, res);
				return;
			}

			response.sendRedirect(request.getContextPath() + "/");
			return;

		} else {
			chain.doFilter(req, res);
		}

	}

	private void parameterNamesLogging(ServletRequest req) {
		for (@SuppressWarnings("rawtypes") Enumeration e = req.getParameterNames(); e.hasMoreElements();) {
			String ParameterNames = (String) e.nextElement();
			logger.debug(ParameterNames + "=" + req.getParameter(ParameterNames) + ",");
		}
	}

	private boolean loginValidation(String uri, HttpSession cSession, HttpServletRequest request, HttpServletResponse response) throws Exception {

		if (cSession.getAttribute(CommonConstants.LOGIN) != null ? !SessionManager.getUserId(request).equals("") : false) {
			return true; // logined user
		}

		if (uri.endsWith(".do")) {

			redirectToLoginPath(request, response);

		} else if (uri.endsWith(".json") || uri.endsWith(".excel")) {

			response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			return false;

		} else if ( uri.endsWith(".view")) {

			cSession.setAttribute("pop", false);
			if(request.getParameter("pop") != null ? request.getParameter("pop").equals("true") : false) {
				cSession.setAttribute("pop", true);
			}

			redirectToLoginPath(request, response);
		}

		response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
		return false;
	}

	private boolean serviceTypeValidation(String uri, HttpSession cSession, HttpServletRequest request, HttpServletResponse response) throws IOException {

		String serviceType = request.getParameter("serviceType");

		if(serviceType == null ? true : serviceType.isEmpty()) {

			return true;
		}

		LoginVo loginVo = (LoginVo) cSession.getAttribute(CommonConstants.LOGIN);

		if(loginVo.getUseServiceTypes().equals(CommonConstants.USER_SERVICETYPE_NO_CHECK)) {

			return true;

		} else if(loginVo.getUseServiceTypes().contains(serviceType)) {

			return true;

		} else {

			redirectToLoginPath(request, response);
			return false;
		}

	}

	private boolean authIgnoreCommands(String cmd) {

		if(cmd == null) {
			return false;
		}

		if(		cmd.startsWith("LIST")
			||	cmd.startsWith("DETAIL")
			||	cmd.startsWith("COMBO")
			||	cmd.startsWith("INSERT")
			||	cmd.startsWith("UPDATE")
			||	cmd.startsWith("DELETE")
			||	cmd.startsWith("APPROVE")
			||	cmd.startsWith("REJECT")
			||	cmd.startsWith("REDEPLOY")
			||	cmd.startsWith("TRANSACTION")
			||	cmd.startsWith("UPLOAD")
			||	cmd.startsWith("INITIALIZE")
			||	cmd.startsWith("CLONE")
			||	cmd.startsWith("CHANGE")) {
			return true;
		} else {
			return false;
		}
	}

	private boolean readAuthIgnoreCommands(String cmd) {

		if(cmd == null) {
			return false;
		}

		if(		cmd.startsWith("LIST")
			|| 	cmd.startsWith("DETAIL")
			|| 	cmd.startsWith("COMBO")
			|| 	cmd.startsWith("CHANGE")) {
			return true;
		} else {
			return false;
		}
	}

	private void redirectToLoginPath(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String loginPath = request.getContextPath() + "/emergency.jsp";
		logger.info("DispatcherType =" + request.getDispatcherType()+ ", loginPath =" + loginPath);
		response.sendRedirect(loginPath);
	}

}
