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 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 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;
	    }
}

