package nlib.sch.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.ui.ModelMap;

import nlib.cmm.Constant;
import nlib.cmm.service.CmmAmsDocTableOfContentsVO;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import egovframework.rte.fdl.cmmn.exception.EgovBizException;
import egovframework.rte.fdl.property.EgovPropertyService;
import egovframework.rte.fdl.security.userdetails.util.EgovUserDetailsHelper;
import egovframework.rte.psl.dataaccess.util.EgovMap;
 

/**
 *
 * Util 클래스
 *
 */
@Component
public class NlibCmmUtil {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(NlibCmmUtil.class);
	public static String DEFAULT_DELIMITER = "-";
	protected static EgovPropertyService propertyService;

	@Resource(name = "propertiesService")
	private EgovPropertyService propertyServiceInstance;
	
	@PostConstruct
	private void init() {
		propertyService = propertyServiceInstance;
	}
	public static String reflectionToString(Object obj) {
		return ToStringBuilder.reflectionToString(obj);
	}
	public static boolean isRoleKdm() {
		List<String> listRole = (List<String>) EgovUserDetailsHelper.getAuthorities();
	    for (String role : listRole) {
	    	if (Constant.AUTH_ROLE_KDM.equals(role)) {
	    		return true;
	    	}
	    }
	    return false;
	}
	public static boolean isRoleSysKdm() {
		List<String> listRole = (List<String>) EgovUserDetailsHelper.getAuthorities();
	    for (String role : listRole) {
	    	if (Constant.AUTH_ROLE_SYM.equals(role)) {
	    		return true;
	    	}
	    }
	    return false;
	}
	
	public static String clearXSS(String value) {
		if (value == null || value.trim().equals("")) {
			return "";
		}
		String returnValue = value;
		returnValue = returnValue.replaceAll("&", "&amp;");
		returnValue = returnValue.replaceAll("<", "&lt;");
		returnValue = returnValue.replaceAll(">", "&gt;");
		returnValue = returnValue.replaceAll("'", "&#39;");
		returnValue = returnValue.replaceAll("eval\\((.*)\\)", "");
		returnValue = returnValue.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
		returnValue = returnValue.replaceAll("\"", "&quot;");
		returnValue = returnValue.replaceAll("\\(", "&#40;").replaceAll("\\)", "&#41;");
		returnValue = returnValue.replaceAll("script", "");
		returnValue = returnValue.replaceAll("alert", "");
		return returnValue;
	}
	
	public static String escapeNewlineToBr(String text) {
		String str = text;
		if (StringUtils.isEmpty(str)) return str;
		
		if (str.indexOf("\\r") >= 0) str = str.replaceAll("\\\\r", "\r");
		if (str.indexOf("\\n") >= 0) str = str.replaceAll("\\\\n", "\n");
		if (str.indexOf("\r\n") >= 0 || str.indexOf("\n") >= 0 || str.indexOf("\r") >= 0) {
			str = str.replaceAll("\\r\\n", "<br/>");
			str = str.replaceAll("\\r", "<br/>");
			str = str.replaceAll("\\n", "<br/>");
		}
		return str;
	}
	public static String escapeNewlineToSpace(String text) {
		String str = text;
		if (StringUtils.isEmpty(str)) return str;
		if (str.indexOf("\\r") >= 0) str = str.replaceAll("\\\\r", "\r");
		if (str.indexOf("\\n") >= 0) str = str.replaceAll("\\\\n", "\n");
		if (str.indexOf("\r\n") >= 0 || str.indexOf("\n") >= 0 || str.indexOf("\r") >= 0) {
			str = str.replaceAll("\\r\\n", "");
			str = str.replaceAll("\\r", "");
			str = str.replaceAll("\\n", "");
		}
		str = str.replaceAll("\"", "");
		str = str.replaceAll("'", "");
		return str;
	}
	public static String cut(String text, int size) {
		return cut(text, size, "");
	}
	public static String cut(String text, int size, String suffix) {
		if (text == null) {
		return "";
		}
		if (text.length() < size) {
		return text;
		}
		size = size - suffix.length();
		return StringUtils.substring(text, 0, size) + suffix;
	}
	public static boolean isConsecutive(String str, int n) {
		int sumOfDifferences = 0;
		int lastTemp = 0;
		Boolean consecutive = false;
		for (int i = 0; i < str.length() - 1; i++) {
		  int temp = str.charAt(i) - str.charAt(i + 1);
		  if (temp != lastTemp) {
		    sumOfDifferences = 0;
		  }
		  if (temp == 1 || temp == -1) {
		    sumOfDifferences += temp;
		  } else {
		    sumOfDifferences = 0;
		  }
		  if (sumOfDifferences == n - 1 || sumOfDifferences == ((n - 1) * -1)) {
		    consecutive = true;
		    break;
		  }
		  lastTemp = temp;
		}
		return consecutive;
	}
	public static boolean regexFind(String str, String regex) {
	    Pattern pattern = Pattern.compile(regex);
	    Matcher matcher = pattern.matcher(str);
	    return matcher.find();
	}
	public static String generateRandomString(String allowed, int length) {
		Random random = new Random();
		StringBuilder sb = new StringBuilder(length);
		for (int i = 0; i < length; i++) {
		  sb.append(allowed.charAt(random.nextInt(allowed.length())));
		}
		return sb.toString();
	}
	public static String getIpAddress(HttpServletRequest req) {
		String ipAddress = "";
		if (req.getHeader("X-Forwarded-For") == null) {
		  ipAddress = req.getRemoteAddr();
		} else {
		  ipAddress = req.getHeader("X-Forwarded-For");
		  int idx = ipAddress.indexOf(',');
		  if (idx > -1) {
		    ipAddress = ipAddress.substring(0, idx);
		  }
		}
		return ipAddress;
	}
	public static String returnUrl(HttpServletRequest req, String parameterName) {
	    String url = req.getRequestURI();
	    if (url.startsWith("/logout") || url.startsWith("/error") || "/".equals(url)) {
	      return "";
	    }
	    String queryString = req.getQueryString();
	    if (queryString != null) {
	      url += "?" + queryString;
	      try {
	        url = URLEncoder.encode(url, Constant.ENCODING_UTF8);
	      } catch (UnsupportedEncodingException e) {
	        url = "";
	      }
	    }
	    return "?" + parameterName + "=" + url;
	}
	
	public static String getUrl(HttpServletRequest req, String domain) {
	    final String uri = req.getRequestURI();
	    final String queryString = req.getQueryString();
	    String url = "";
		url = domain + uri;
		if (StringUtils.isNotBlank(queryString)) {
			url += "?" + queryString;
	    }
	    return url;
	}
	public static int getTridentVersion(String userAgent) {
	    String lowerUserAgent = userAgent.toLowerCase();
	    int start = lowerUserAgent.indexOf("trident/");
	    if (start == -1) {
	      return 0;
	    }
	    String trident = lowerUserAgent.substring(start + 8, start + 9);
	    return NumberUtils.toInt(trident);
	}
	public static String getPropertyStr(String key) {
		String str = "";
		if (org.apache.commons.lang3.StringUtils.isNotBlank(key)) str = propertyService.getString(key);
		return str;
	}
	public static String deleteChar(String str) {
		if (StringUtils.isEmpty(str)) return str;
		
		String  regExpNumber = "[^0-9]";
		return str.replaceAll(regExpNumber, "");
	}
	@SuppressWarnings("rawtypes")
	public static boolean isEmpty(Map map, String key) {
		boolean isEmpty = true;
		if (map == null) return isEmpty;

		Object obj = map.get(key);
		if ( obj != null 
				&& !StringUtils.isEmpty(obj.toString())
				&& !(obj+"").equals("null")) {
			
			isEmpty = false;
		}
		return isEmpty;
	}
	public static boolean checkMaxbyte(String chkString, int maxbyte) {
		boolean checkResult = true;
		if (StringUtils.isBlank(chkString)) return checkResult;
		int bytes = 0;
		try {
			bytes = chkString.getBytes(Constant.ENCODING_UTF8).length;
			if (bytes > maxbyte) checkResult = false;
		} catch (UnsupportedEncodingException e) {
			LOGGER.error("fail in checkMaxbyte() maxbyte="+maxbyte+", bytes="+bytes+", chkString="+chkString, e);
			checkResult = false;
		} catch (Exception e) {
			LOGGER.error("fail in checkMaxbyte() maxbyte="+maxbyte+", bytes="+bytes+", chkString="+chkString, e);
			checkResult = false;
		}
		return checkResult;
	}
	public static String[] getValueArr(List<EgovMap> list, String key) {
		String[] exidArr = null;
		if (list == null || list.size() == 0) return exidArr;
		exidArr = new String[list.size()];
		for (int i=0; i<list.size(); i++) {
			EgovMap data = list.get(i);
			String exid = getStr(data, key);
			exidArr[i] = exid;
		}
		return exidArr;
	}
    public static String[] splitStr(String splittee, String splitChar){
        String taRetVal[] = null;
        StringTokenizer toTokenizer = null;
        int tnTokenCnt = 0;
        try {
            toTokenizer = new StringTokenizer(splittee, splitChar);
            tnTokenCnt = toTokenizer.countTokens();
            taRetVal = new String[tnTokenCnt];

            for(int i=0; i<tnTokenCnt; i++) {
                if(toTokenizer.hasMoreTokens())	taRetVal[i] = toTokenizer.nextToken();
            }
        } catch (NullPointerException e) {
        	LOGGER.debug("null in splitStr() : array(0)");
        	taRetVal = new String[0];
        } catch (Exception e) {
        	LOGGER.debug("Error in splitStr() : array(0)");
            taRetVal = new String[0];
        }
        return taRetVal ;
    }
	public static String getNumberDashAddFmt(String value01, String value02, String value03) {
		String str = "";
		if( org.apache.commons.lang3.StringUtils.isBlank(value02) || org.apache.commons.lang3.StringUtils.isBlank(value03)){
		}else{
			str = value01 + DEFAULT_DELIMITER + value02 + DEFAULT_DELIMITER + value03;
		}
		return str;
	}
	@SuppressWarnings("rawtypes")
	public static String getStr(Map map, String key) {
		String str = "";
		if (isEmpty(map, key)) return str;
		str = map.get(key)+"";
		return str;
	}
	@SuppressWarnings("rawtypes")
	public static Integer getInteger(Map map, String key) {
		Integer value = null;
		if (isEmpty(map, key)) return value;
		try {
			value = new Integer(map.get(key)+"");
		} catch (NumberFormatException e1) {
			LOGGER.error("fail in getInteger() key="+key+", map="+map, e1); 
		} catch (Exception e2) {
			LOGGER.error("fail in getInteger() key="+key+", map="+map, e2); 
		}
		return value;
	}
	@SuppressWarnings("rawtypes")
	public static BigDecimal getBigDecimal(Map map, String key) {
		BigDecimal value = null;
		if (isEmpty(map, key)) return value;
		
		try {
			value = new BigDecimal(map.get(key)+"");
		} catch (NumberFormatException e1) {
			LOGGER.error("fail in getBigDecimal() key="+key+", map="+map, e1); 
		} catch (Exception e2) {
			LOGGER.error("fail in getBigDecimal() key="+key+", map="+map, e2); 
		}
		return value;
	}
	public static String getPassStr() {
		String str = "";
		Random r = new Random();
		for(int i = 0; i < 10; i++){
			char lowerStr = (char)(r.nextDouble() * 26 + 97);
			if(i%2 == 0){
				str += (int)(r.nextDouble() * 10);
			}else{
				str += lowerStr;
			}
		}
		return str;
	}
	public static String getPassStr(int cnt) {
		String str = "";
		Random r = new Random();
		for(int i = 0; i < cnt; i++){
			char lowerStr = (char)(r.nextDouble() * 26 + 97);
			if(i%2 == 0){
				str += (int)(r.nextDouble() * cnt);
			}else{
				str += lowerStr;
			}
		}
		return str;
	}
	public static String getIp(HttpServletRequest request)  throws IOException, InvocationTargetException, SQLException, Exception {
		
		String ip = request.getHeader("X-Forwarded-For");
		
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		 
		return ip;
	}
	public static boolean checkIPMatching(String pattern, String address)
	{
	    if (pattern.equals("*.*.*.*") || pattern.equals("*"))
	        return true;

	    String[] mask = pattern.split("\\.");
	    String[] ip_address = address.split("\\.");
	    for (int i = 0; i < mask.length; i++)
	    {
	        if (mask[i].equals("*") || mask[i].equals(ip_address[i]))
	            continue;
	        else if (mask[i].contains("-"))
	        {
	            byte min = Byte.parseByte(mask[i].split("-")[0]);
	            byte max = Byte.parseByte(mask[i].split("-")[1]);
	            byte ip = Byte.parseByte(ip_address[i]);
	            if (ip < min || ip > max)
	                return false;
	        }
	        else
	            return false;
	    }
	    return true;
	}
	public static String getRandomNum(int size) {
		String strRandom = "";
		Random rand = new Random();
		for (int i = 0; i < size; i++) {
			strRandom += String.valueOf(rand.nextInt(10));
		}
		return strRandom;
	}
	public static boolean isMobile(final HttpServletRequest req) {
	    String ua = StringUtils.defaultString(req.getHeader("User-Agent"), "").toLowerCase();
	    if (ua.indexOf(Constant.ANDROID) > -1 || ua.indexOf(Constant.IOS) > -1 || ua.indexOf("mobile") > -1) {
	      return true;
	    }
	    return false;
	 }
	 public static String getContextPath(final HttpServletRequest req, final String path) {
	    //if (isApp(req)) {
	      return Constant.PREFIX_M + (path.startsWith("/") ? path : "/" + path);
	    //}
	   // return path;
	 }
	public static String unscript(String data) {
        if (data == null || data.trim().equals("")) {
            return "";
        }
        
        String ret = data;
        
        ret = ret.replaceAll("<(S|s)(C|c)(R|r)(I|i)(P|p)(T|t)", "&lt;script");
        ret = ret.replaceAll("</(S|s)(C|c)(R|r)(I|i)(P|p)(T|t)", "&lt;/script");
        
        ret = ret.replaceAll("<(O|o)(B|b)(J|j)(E|e)(C|c)(T|t)", "&lt;object");
        ret = ret.replaceAll("</(O|o)(B|b)(J|j)(E|e)(C|c)(T|t)", "&lt;/object");
        
        ret = ret.replaceAll("<(A|a)(P|p)(P|p)(L|l)(E|e)(T|t)", "&lt;applet");
        ret = ret.replaceAll("</(A|a)(P|p)(P|p)(L|l)(E|e)(T|t)", "&lt;/applet");
        
        ret = ret.replaceAll("<(E|e)(M|m)(B|b)(E|e)(D|d)", "&lt;embed");
        ret = ret.replaceAll("</(E|e)(M|m)(B|b)(E|e)(D|d)", "&lt;embed");
        
        ret = ret.replaceAll("<(F|f)(O|o)(R|r)(M|m)", "&lt;form");
        ret = ret.replaceAll("</(F|f)(O|o)(R|r)(M|m)", "&lt;form");

        return ret;
    }
    public static DataMap getMapFromJsonObject( JSONObject jsonObj ){
    	DataMap map = null;
        try {
            map = new ObjectMapper().readValue(jsonObj.toString(), DataMap.class) ;
        } catch (JsonParseException e) {
        	LOGGER.error("Error in getMapFromJsonObject()", e);
        } catch (JsonMappingException e) {
        	LOGGER.error("Error in getMapFromJsonObject()", e);
        } catch (IOException e) {
        	LOGGER.error("Error in getMapFromJsonObject()", e);
        }
        return map;
    }
    public static DataMap getMapFromJsonObject(DataMap map, JSONObject jsonObj){
        try {
            map = new ObjectMapper().readValue(jsonObj.toString(), DataMap.class) ;
        } catch (JsonParseException e) {
        	LOGGER.error("Error in getMapFromJsonObject()", e);
        } catch (JsonMappingException e) {
        	LOGGER.error("Error in getMapFromJsonObject()", e);
        } catch (IOException e) {
        	LOGGER.error("Error in getMapFromJsonObject()", e);
        }
        return map;
    }
	public static List<DataMap> getListMapFromJsonArray( JSONArray jsonArray ) {
        List<DataMap> list = new ArrayList<DataMap>();
        if( jsonArray != null ){
            int jsonSize = jsonArray.length();
            for( int i = 0; i < jsonSize; i++ ){
            	DataMap map = NlibCmmUtil.getMapFromJsonObject( ( JSONObject ) jsonArray.get(i) );
                list.add( map );
            }
        }
        return list;
    }
	public static String getAisSidoName(String sido) {
		String rtnStr = "";
		for(int i=0;i<Constant.AIS_SIDO_PARAM_NAME_ARRAY.length;i++){
			if(Constant.AIS_SIDO_PARAM_NAME_ARRAY[i].equals(sido)){
				rtnStr = Constant.AIS_SIDO_NAME_ARRAY[i];
				break;
			}
		}
		return rtnStr;
	}
	public static void checkCookie(final HttpServletRequest req , final HttpServletResponse res){
	/*	if(StringUtils.isBlank(getCookieId(req))){
			setCookieId(req,res);
		}*/
		if(StringUtils.isBlank(getCookie(req , propertyService.getString("kccf.cookie.addr.key")))){
			setEncoderCookie(res,  propertyService.getString("kccf.cookie.addr.key"), propertyService.getString("kccf.default.pscHst"));
		}
	}
	public static String getCookie(final HttpServletRequest req, String Name){
		String cookieValue = "";
		Cookie[] cookies = req.getCookies();
		if(cookies != null && cookies.length > 0){
			for(Cookie cookie : cookies){
				if(Name.equals(cookie.getName())){
					cookieValue = cookie.getValue();
					break;
				}
			}
		}
		return cookieValue;
	}
	public static String getDecoderCookie(final HttpServletRequest req, String Name){
		String cookieValue = "";
		Cookie[] cookies = req.getCookies();
		if(cookies != null && cookies.length > 0){
			for(Cookie cookie : cookies){
				if(Name.equals(cookie.getName())){
					try {
						cookieValue = java.net.URLDecoder.decode(cookie.getValue(),Constant.ENCODING_UTF8);
					} catch (UnsupportedEncodingException e) {
						LOGGER.error("fail in getDecoderCookie()" , e); 
					} catch (Exception e) {
						LOGGER.error("fail in getDecoderCookie()", e);
					}
					break;
				}
			}
		}
		return cookieValue;
	}
	public static String getCookieIdKey(){
		return  propertyService.getString("kccf.cookie.id.key");
	}
	
	public static String getCookieId(final HttpServletRequest req){
		String cookieId = "";
		String key = getCookieIdKey();
		Cookie[] cookies = req.getCookies();
		if(cookies != null && cookies.length > 0){
			for(Cookie cookie : cookies){
				if(key.equals(cookie.getName())){
					try {
					cookieId = java.net.URLDecoder.decode( cookie.getValue(),Constant.ENCODING_UTF8);
					} catch (UnsupportedEncodingException e) {
						LOGGER.error("fail in getCookieId()" , e); 
					} catch (Exception e) {
						LOGGER.error("fail in getCookieId()", e);
					}
					break;
				}
			}
		}
		return cookieId;
	}
	public static String getNewCookieId(final HttpServletRequest req){
		String key = getCookieIdKey();
		String value = "";
		try {
			value = java.net.URLEncoder.encode( encryptPassword(getPassStr(50), key) , Constant.ENCODING_UTF8 );
		} catch (UnsupportedEncodingException e) {
			LOGGER.error("Error in getNewCookieId()", e);
		} catch (Exception e) {
			LOGGER.error("Error in getNewCookieId()", e);
		}
		return value;
	}
	public static void setCookieId(final HttpServletRequest req, final HttpServletResponse res){
		String key = getCookieIdKey();
		String value = "";
		
		try {
			value = java.net.URLEncoder.encode( encryptPassword(getPassStr(50), key) , Constant.ENCODING_UTF8 );
		} catch (UnsupportedEncodingException e) {
			LOGGER.error("Error in setCookieId()", e);
		} catch (Exception e) {
			LOGGER.error("Error in setCookieId()", e);
		}
		
		/* 2019.02.26 웹취약점 수정사항 => 1시간마다 쿠키 만료되고 있음
		String maxAge = String.valueOf((60*60*24*365)*10);
		if (maxAge.matches("[0-9]+")) {
			Cookie cookie = new Cookie(key,value);
			// 수정 : 외부입력값 검증 후 쿠키 유효시한 설정에 사용
			int t = Integer.parseInt(maxAge);
			if ( t > 3600 ) {
				t = 3600;
			}
			cookie.setMaxAge(t);
			cookie.setPath("/");
			res.addCookie(cookie);
		}
		*/
		
		// 쿠키 유효기간 1년으로 변경 (2019.08.08)
		int maxAge = 60*60*24*365; // 1년
		Cookie cookie = new Cookie(key,value);
		cookie.setMaxAge(maxAge);
		cookie.setPath("/");
		res.addCookie(cookie);
	}
	
	public static void setCookie(final HttpServletResponse res, String key, String value){
		/* 2019.02.26 웹취약점 수정사항 => 1시간마다 쿠키 만료되고 있음
		String maxAge = String.valueOf((60*60*24*365)*10);
		if (maxAge.matches("[0-9]+")) {
			Cookie cookie = new Cookie(key,value);
			// 수정 : 외부입력값 검증 후 쿠키 유효시한 설정에 사용
			int t = Integer.parseInt(maxAge);
			if ( t > 3600 ) {
				t = 3600;
			}
			cookie.setMaxAge(t);
			cookie.setPath("/");
			res.addCookie(cookie);
		}
		*/
		
		// 쿠키 유효기간 1년으로 변경 (2019.08.08)
		int maxAge = 60*60*24*365; // 1년
		Cookie cookie = new Cookie(key,value);
		cookie.setMaxAge(maxAge);
		cookie.setPath("/");
		res.addCookie(cookie);
	}
	
	public static void setEncoderCookie(final HttpServletResponse res, String key, String value){
		
		try {
			value = java.net.URLEncoder.encode(value,Constant.ENCODING_UTF8);
		} catch (UnsupportedEncodingException e) {
			LOGGER.error("Error in setEncoderCookie()", e);
		} catch (Exception e) {
			LOGGER.error("Error in setEncoderCookie()", e);
		}

		/* 2019.02.26 웹취약점 수정사항 => 1시간마다 쿠키 만료되고 있음
		String maxAge = String.valueOf((60*60*24*365)*10);
		if (maxAge.matches("[0-9]+")) {
			Cookie cookie = new Cookie(key,value);
			// 수정 : 외부입력값 검증 후 쿠키 유효시한 설정에 사용
			int t = Integer.parseInt(maxAge);
			if ( t > 3600 ) {
				t = 3600;
			}
			cookie.setMaxAge(t);
			cookie.setPath("/");
			res.addCookie(cookie);
		}
		*/
		
		// 쿠키 유효기간 1년으로 변경 (2019.08.08)
		int maxAge = 60*60*24*365; // 1년
		Cookie cookie = new Cookie(key,value);
		cookie.setMaxAge(maxAge);
		cookie.setPath("/");
		res.addCookie(cookie);
	}
	
	public static void removeCookie(final HttpServletRequest req, final HttpServletResponse res, String key){
		Cookie[] cookies = req.getCookies();
		if(cookies != null && cookies.length > 0){
			for(Cookie cookie : cookies){
				if(key.equals(cookie.getName())){
					cookie.setMaxAge(0);
					cookie.setPath("/");
					cookie.setSecure(true);	//중요정보 평문전송 (HTTP): 취약점 수정
					String val = cookie.getValue();
					String filtered_val = val.replaceAll("\r","").replaceAll("\n","");
					Cookie cookie2 = new Cookie(key, filtered_val);
					res.addCookie(cookie2);
					break;
				}
			}
		}
	}
	private static String encryptPassword(String key, String val) throws NoSuchAlgorithmException {
		if (key == null) {
		    return "";
		}
		byte[] hashValue = null; // 해쉬값
		MessageDigest md = MessageDigest.getInstance("SHA-512");
		md.reset();
		md.update(val.getBytes());
		hashValue = md.digest(key.getBytes());
		
		return new String(Base64.encodeBase64(hashValue)).replaceAll("\\+", "").replaceAll("=", "");
	}
	public static boolean isSido(String str){
		boolean isSido = false;
		for(int i=0; i<Constant.AIS_SIDO_NAME_ARRAY.length;i++){
			if(str.indexOf( Constant.AIS_SIDO_NAME_ARRAY[i] ) > -1 ){
				isSido = true;
				break;
			}
			if(str.indexOf( Constant.AIS_SIDO_PARAM_NAME_ARRAY[i] ) > -1 ){
				isSido = true;
				break;
			}
		}
		return isSido;
	}
	public static String changeSido(String str){
		if(str == null || "".equals(str)) return "";
		String rtnSido = "";
		for(int i=0; i<Constant.AIS_SIDO_NAME_ARRAY.length;i++){
			if(str.indexOf( Constant.AIS_SIDO_NAME_ARRAY[i] ) > -1 ){
				rtnSido = Constant.AIS_SIDO_PARAM_NAME_ARRAY[i];
				break;
			}
			if(str.indexOf( Constant.AIS_SIDO_PARAM_NAME_ARRAY[i] ) > -1 ){
				rtnSido = Constant.AIS_SIDO_PARAM_NAME_ARRAY[i];
				break;
			}
		}
		return rtnSido;
	}
	public static void setAmsPathModelMap(HttpServletRequest req, ModelMap modelMap){
		// ams 경로
		String amsAssetsPath = getPropertyStr(Constant.AMS_SERVER_KEY) + getPropertyStr(Constant.AMS_ASSETS_PATH_KEY);
		String amsThumbnailPath = getPropertyStr(Constant.AMS_THUMBNAIL_PATH_KEY);
		String amsImagePath = getPropertyStr(Constant.AMS_FILE_PATH_KEY);
		modelMap.addAttribute("amsAssetsPath", amsAssetsPath);
		modelMap.addAttribute("amsThumbnailPath", amsThumbnailPath);
		modelMap.addAttribute("amsImagePath", amsImagePath);
	}
	
	public static void setNfsPathModelMap(HttpServletRequest req, ModelMap modelMap){
		// ams 경로
		String nfsNasPath = getPropertyStr(Constant.NFS_NAS_KEY);
		String nfsDocPath = getPropertyStr(Constant.NFS_DOC_KEY);
		modelMap.addAttribute("nfsNasPath", nfsNasPath);
		modelMap.addAttribute("nfsDocPath", nfsDocPath);
	}
	
	public static String getAssetImageUrl(String imagePath) {
		String imageUrl = "";
		if (StringUtils.isEmpty(imagePath)) return imageUrl;
		
		String amsAssetsPath = getPropertyStr(Constant.AMS_SERVER_KEY) + getPropertyStr(Constant.AMS_ASSETS_PATH_KEY);
		String amsThumbnailPath = getPropertyStr(Constant.AMS_THUMBNAIL_PATH_KEY);
		if (imagePath.startsWith("http")) { // http 포함한 전체 경로일 경우 ex) object storage 이미지
			imageUrl = imagePath;
			
		} else if (imagePath.indexOf("/") >= 0) { // ex) 2/2/7292_thumbnail.jpg
			imageUrl = amsAssetsPath + "/" + imagePath;
			
		} else {
			imageUrl = amsAssetsPath + "/" + amsThumbnailPath + "/" + imagePath; // ex) ac6be22ee9db4414aeb4dab6078d27feb723f1c0.jpg
		}
		
		imageUrl = imageUrl.replaceAll("//", "/");
		imageUrl = imageUrl.replaceAll(":/", "://"); // ex) https:/ => https://
		
		return imageUrl;
	}
	
	
	public static String getContentsImageUrl(String imagePath) {
		String imageUrl = "";
		if (StringUtils.isEmpty(imagePath)) return imageUrl;
		
		String amsAssetsPath = getPropertyStr(Constant.KCCF_HOME_KEY);
		if (imagePath.startsWith("http")) { // http 포함한 전체 경로일 경우 ex) object storage 이미지
			imageUrl = imagePath;
			
		} else if (imagePath.indexOf("/") >= 0) { // ex) 2/2/7292_thumbnail.jpg
			imageUrl = amsAssetsPath + "/" + imagePath;
			
		} else {
			imageUrl = amsAssetsPath + "/" + imagePath; // ex) ac6be22ee9db4414aeb4dab6078d27feb723f1c0.jpg
		}
		
		imageUrl = imageUrl.replaceAll("//", "/");
		imageUrl = imageUrl.replaceAll(":/", "://"); // ex) https:/ => https://
		
		return imageUrl;
	}
	
	
	public static void setUploadPathModelMap(HttpServletRequest req, ModelMap modelMap){
		// 서버경로 (upload폴더 상위경로) : 로컬 개발시 upload 파일이 로컬에 존재하지 않을 경우 사용
		String uploadHomePath = getPropertyStr(Constant.UPLOAD_HOME_KEY);
		modelMap.addAttribute("uploadHomePath", uploadHomePath);
	}
	
	/**
	 * 자산미디어 - 문서 목차 문자열 파싱
	 * 
테스트 목차 -----1
제1장 6.25전쟁 전투수기 -----100

발간사 ---2 ***1
축간사(창녕군수) ---4
축간사(창녕군의회의장)---5
제1장 6.25전쟁 전투수기 ***2
	 끊어진 한강 철교 빈 보트로 건너다.(성경상) ---12
	 포탄이 날아들어 전우 3명이 즉사하다.(김윤규) ---16
	 *
	 * @param str
	 * @return
	 * @throws Exception
	 */
	public static List<CmmAmsDocTableOfContentsVO> parseTableOfContents(String str) {
		List<CmmAmsDocTableOfContentsVO> list = new ArrayList<CmmAmsDocTableOfContentsVO>();
		if (StringUtils.isEmpty(str)) return list;

		
		String[] lineArr = str.split("\n");
		int listIdx = 1;
		for (int i=0; i<lineArr.length; i++) {
			
			String title = "";
			String pageNum = null;
			Integer ocrFileNum = null;

			String line = lineArr[i];
//			String str2 = "";
			String pattern1 = "---";
			String pattern2 = "\\*\\*\\*";
			int idx1 = line.indexOf("---");
			int idx2 = line.indexOf("***");
//			LOGGER.debug("parseTableOfContents() i={}, idx1={}, idx2={}, line={}", i, idx1, idx2, line);
			List<String> errorList = new ArrayList<String>();

			if (idx1 >= 0 && idx2 >= 0) { // ex) 발간사 ---2 ***1
				String[] arr = line.split(pattern1);
				title = arr[0];
				String[] arr2 = arr[1].split(pattern2);
				
				try {
					if (arr2.length == 2) {
						pageNum = parseTableOfContentsPageNum(arr2[0]);
						ocrFileNum = new Integer(StringUtils.trim(arr2[1]).replaceAll(" ", ""));
						
					} else if (arr2.length == 1) { // ex) 1. 옹기의 지역적인 특성 ---7 ***
						pageNum = parseTableOfContentsPageNum(arr2[0]);
						ocrFileNum = new Integer(""); // 강제로 에러발생시킴
					}
				} catch (Exception e) {
					errorList.add(listIdx+"\t"+e.getMessage());
				}
			} else if (idx1 >= 0 && idx2 < 0) { // ex) 축간사(창녕군수) ---4
				String[] arr = line.split(pattern1);
				title = arr[0];
				try {
					pageNum = parseTableOfContentsPageNum(arr[1]);
				} catch (Exception e) {
					errorList.add(listIdx+"\t"+e.getMessage());
				}
				
			} else if (idx1 < 0 && idx2 >= 0) { // ex) 제1장 6.25전쟁 전투수기 ***2
				String[] arr = line.split(pattern2);
				title = arr[0];
				try {
					if (arr.length == 2) {
						ocrFileNum = new Integer(StringUtils.trim(arr[1]).replaceAll(" ", ""));
						
					} else if (arr.length == 1) { // ex) -참고문헌 ***
						ocrFileNum = new Integer(""); // 강제로 에러발생시킴
					}
				} catch (Exception e) {
					errorList.add(listIdx+"\t"+e.getMessage());
				}
				
			} else {
				title = line;
			}
			
			list.add(new CmmAmsDocTableOfContentsVO(title, pageNum, ocrFileNum, errorList));
			listIdx++;
		}
		
		return list;
	}
	
	/**
	 * PDF 목차 페이지번호 파싱
	 * @param pageNumStr
	 * @return
	 * @throws Exception
	 */
	public static String parseTableOfContentsPageNum(String pageNumStr) throws Exception {
		if (StringUtils.isEmpty(pageNumStr)) {
			pageNumStr = new Integer(pageNumStr).toString(); // 강제로 Exception 발생시킴
		}
		
		pageNumStr = StringUtils.trim(pageNumStr).replaceAll(" ", "");
		
		boolean isPageNum = true;
		for (int i=0; i<pageNumStr.length(); i++) {
			char c = pageNumStr.charAt(i);
			if (!Pattern.matches("[0-9|\\.|•|\\(\\)|a-zA-Z|〜|~|쪽|장|一-十|四五六|\\,|/|후|天|地|Ⅰ-ⅻ|【】]", Character.toString(c))) {
				isPageNum = false;
				break;
			}
		}
		if (!isPageNum) {
			pageNumStr = new Integer(pageNumStr).toString(); // 강제로 Exception 발생시킴
		}

		return pageNumStr;
	}
	
	/**
	 * ezpdfwebviewer 좌측 목차 표시 위한 html markup 생성
	 * @return
	 * @throws Exception
	 */
	public static String makeTableOfContentsMarkup(List<CmmAmsDocTableOfContentsVO> list, String delimiter) throws Exception {
		StringBuffer sb = new StringBuffer();;
		
		String title = "";
		int titleDepth = 1;
		int prevTitleDepth = 100;
		String pageNum = null;
		Integer ocrFileNum = null;
		boolean hasOcrFileNum = false;
		
		for (int i=0; list!=null && i<list.size(); i++) {
			CmmAmsDocTableOfContentsVO vo = list.get(i);
			title = vo.getTitle();
			if (StringUtils.isEmpty(title)) continue;

			if ("||".equals(delimiter)) {
				title = title.replaceAll("\\|\\|", " "); // 중간에서 잘리지 않도록 미리 치환
			}
			
			if (title.indexOf("\"") >= 0) {
				title = title.replaceAll("\"", " "); // 따옴표 치환
			}
			pageNum = vo.getPageNum();
			
			ocrFileNum = vo.getOcrFileNum();
			
			if (ocrFileNum != null) {
				hasOcrFileNum = true;
			} else {
				hasOcrFileNum = false;
			}
			
			if (title.startsWith(" ") || title.startsWith("\t")) {
				if (title.startsWith("      ")) {		// 공백6칸
					titleDepth = 4;
				} else if (title.startsWith("     ")) {	// 공백5칸
					titleDepth = 4;
				} else if (title.startsWith("    ")) {	// 공백4칸
					titleDepth = 3;
				} else if (title.startsWith("   ")) {	// 공백3칸
					titleDepth = 3;
				} else if (title.startsWith("  ")) {	// 공백2칸
					titleDepth = 2;
				} else if (title.startsWith(" ")) {		// 공백1칸
					titleDepth = 2;
				} else if (title.startsWith(" •")) {	// 공백1칸 +원문자 ex) K163832.pdf
					titleDepth = 2;
				}
			} else {
				titleDepth = 1;
			}
			
			String cssDepth = "";
			if (titleDepth == 1) cssDepth = "d1";
			else if (titleDepth == 2) cssDepth = "d2";
			else if (titleDepth == 3) cssDepth = "d3";
			else if (titleDepth == 4) cssDepth = "d4";
			
			if (hasOcrFileNum) {
	            if (i > 0 && ocrFileNum != null) sb.append(delimiter);
	            title = title.replaceAll("(\r\n|\r|\n|\n\r)", "");
	            sb.append("<p class='"+cssDepth+"'>"+title);
	            if (pageNum != null) sb.append(" - "+pageNum);
	            sb.append("</p>");

	         } else {
	            title = title.replaceAll("(\r\n|\r|\n|\n\r)", "");
	            sb.append("<p class='"+cssDepth+"'>"+title);
	            if (pageNum != null) sb.append(" - "+pageNum);
	            sb.append("</p>");
	         }
			
			// ocrFileNum 위치 검증
			if (titleDepth == 1 && prevTitleDepth > 1 && !hasOcrFileNum) {
				List<String> errorList = vo.getErrorList();
				errorList.add((i+1)+"\t"+"missing divided file number? : "+title+(pageNum!=null ? " - "+pageNum : ""));
			}
			
			
			prevTitleDepth = titleDepth;
		}
		
		return sb.toString();
	}
	
	/**
	 * URL scheme HTTPS로 변경
	 * @param url
	 * @return
	 */
	public static String changeSchemeToHttps(String url) {
		String result = "";
		if (StringUtils.isEmpty(url)) return result;
		
		Pattern p = Pattern.compile("^(http:\\/\\/|https:\\/\\/)?(www\\.)?(.*)$"); // URL 앞부분 패턴
		Matcher m = p.matcher(url);
		if (m.find()) {
			LOGGER.info("changeSchemeToHttps()  m.groupCount()={}, m.group(1)={}, m.group(2)={}, m.group(3)={}, m.group(0)={}", m.groupCount(), m.group(1), m.group(2), m.group(3), m.group(0));
			result = "https://";
			if (m.group(2) != null) result += m.group(2);
			result += m.group(3);
		}
		
		return result;
	}
	
	public static String getLinkUrl(String aId, String mId )throws EgovBizException {

	    	DataMap param = new DataMap();
			param.put("aId", aId);
			param.put("mId", mId);
	    	DataMap media = new DataMap();
	    	String mediaId = media.getString("mediaId");
	    	String mediaInterfaceId = media.getString("mediaInterfaceId");
	    	
	    	String rtnStr = "";
	    	if (StringUtils.isNotEmpty(mediaInterfaceId)) { // mediaInterfaceId가 존재할 경우만 URL 정보 생성
		    	if(media.get("assetType") != null){
		    		if(media.get("assetType").toString().equals("문서") ){		        		
		    			rtnStr = NlibCmmUtil.getPropertyStr(Constant.KCCF_HOME_KEY)+"/npdfView.do?";
		    			rtnStr += "npdf="+Constant.UA_TYPE_R+mediaInterfaceId; // MEDIA 의 INTERFACE_ID 사용
		        		
		    		}else if(media.get("assetType").toString().equals("링크")){
		    			rtnStr = media.get("linkData").toString();
		    		}else{
		    			rtnStr = NlibCmmUtil.getPropertyStr(Constant.KCCF_HOME_KEY)+"/lib/libraryDetail.do?contentId="+mediaId;
		    			rtnStr += "&rfType="+Constant.UA_TYPE_R; // 히스토리 등록 시 사용
		    		}
		    	}
	    	}
	    	return rtnStr;
	    }
}

