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

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.helpers.LogLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.eactive.eai.common.dao.DAOFactory;
import com.eactive.eai.common.property.PropGroupVO;
import com.eactive.eai.common.property.PropertyDAO;
import com.eactive.eai.common.util.UUID;
import com.eactive.eai.rms.common.base.BaseAnnotationController;
import com.eactive.eai.rms.common.combo.ComboService;
import com.eactive.eai.rms.common.combo.ComboVo;
import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.excel.ExcelSheet;
import com.eactive.eai.rms.common.excel.ExcelUtil;
import com.eactive.eai.rms.common.spring.LocaleMessage;
import com.eactive.eai.rms.common.util.CamelCaseUtil;
import com.eactive.eai.rms.common.util.ContainerUtil;
import com.eactive.eai.rms.onl.common.exception.BizException;

import java.nio.file.Files;
import java.nio.file.Paths;

//import SCSL.SLDsFile;

/**
 * <pre>
 *     1. 기능 : 레이아웃 파일 업로드 관리 화면의 컨트롤러
 * </pre>
 *
 * @author : 
 * @version : $Revision: 1.24 $
 * @since : rms 1.0
 */

@Controller
public class LayoutExcelController extends BaseAnnotationController  {

    @Autowired
    @Qualifier("monitoringContext")
    private MonitoringContext monitoringContext;	
	
    @Autowired
	@Qualifier("localeMessage")
	private LocaleMessage localeMessage;
    
	@Autowired
	@Qualifier("layoutExcelService")
	private LayoutExcelService service; 
	
    @Autowired
    private ComboService comboService;      

    @RequestMapping(value= "/onl/admin/rule/layoutExcelMan.view")
	private String viewList(HttpServletRequest request, @RequestParam(value = "cmd", required = false ) String cmd) throws Exception {
		if (cmd == null || "LIST".equals(cmd.toUpperCase())){
			cmd = "";
		}else {
			cmd = CamelCaseUtil.converCamelCase(cmd);
		}
		String path = request.getServletPath();
		return path.split("[.]")[0]+cmd;
	}
    
    @RequestMapping(value= "/onl/admin/rule/layoutExcelMan.do")
    private ModelAndView doView(HttpServletRequest request, String names) throws Exception {
    	ModelAndView mav = new ModelAndView();
    	logger.info("LayoutExcelController - doView [ExcelNames: "+ names +"]");
    	String path = request.getServletPath();
    	mav.setViewName(path.split("[.]")[0]);
    	mav.addObject("ExcelNames", names);
    	return mav;
    }
	
	private HashMap upload(HttpServletRequest request,MultipartFile file) throws Exception{
		String srcFilePath =null;  
    	String dstFilePath =null;
    	String PropPath  =null;
    	String keyFilePath =null;
    	String orgFileNm = "";
		String fileExtension = "";
		String srcFile  = "";
		String dstFile  = "";
		String name = "";
		HashMap resultMap = new HashMap();
		///////////////////////////
		srcFilePath = monitoringContext.getStringProperty(MonitoringContext.SOFTCAMP_SFPATH);
		dstFilePath = monitoringContext.getStringProperty(MonitoringContext.SOFTCAMP_DFPATH); 
		PropPath  = monitoringContext.getStringProperty(MonitoringContext.SOFTCAMP_PROP);
		keyFilePath = monitoringContext.getStringProperty(MonitoringContext.SOFTCAMP_KEY);

		if(srcFilePath ==null|| dstFilePath ==null|| PropPath ==null|| keyFilePath ==null){
			resultMap.put("message"  , "[ERRROR] 문서암호화 해제 property를 확인해주세요.");
			logger.error("[ERRROR] 문서암호화 해제 property를 확인해주세요.");
			return resultMap;
		}
		
 		String message = "";
 		
 		//LOG 파일 위치 프라퍼티로 
        String defaultLogPath = monitoringContext.getStringProperty(
                MonitoringContext.DEFAULT_LOG_PATH, "/fslog/eai/");
    	
        srcFilePath = defaultLogPath + ContainerUtil.getInstanceName()+srcFilePath;
        dstFilePath = defaultLogPath + ContainerUtil.getInstanceName()+dstFilePath;
        
        logger.info("srcFilePath : "+srcFilePath);
    	logger.info("dstFilePath : "+dstFilePath);
    	
    	File sdir = new File(srcFilePath);
    	if (sdir != null && !sdir.exists()) {
            boolean success = sdir.mkdirs();
            if (!success) {
                LogLog.error("Failed to create srcFilePath directory structure: " + 
                             sdir);
                message = "[ERRROR] 문서암호화 해제 property를 확인해주세요.";
				logger.error(message);
                resultMap.put("message"  , message);
    			return resultMap;
            }
        }
    	
    	File tdir = new File(dstFilePath);
    	if (tdir != null && !tdir.exists()) {
            boolean success = tdir.mkdirs();
            if (!success) {
                LogLog.error("Failed to create dstFilePath directory structure: " + 
                		tdir);
                message = "[ERRROR] 문서암호화 해제 property를 확인해주세요.";
				logger.error(message);
                resultMap.put("message"  , message);
    			return resultMap;
            }
        }
 		
 		
 		int idx = 0;
 		

		//1.file upload 
 		if(file != null){
			orgFileNm = file.getOriginalFilename();
			idx = orgFileNm.lastIndexOf(".");
			//파일 확장자
			fileExtension = "."+orgFileNm.substring(idx+1);
			
			UUID uuid = UUID.randomUUID();
	 		name = uuid.toString();
			BufferedOutputStream stream = null;
            try {
            	
                byte[] bytes = file.getBytes();
                stream =new BufferedOutputStream(new FileOutputStream(new File(srcFilePath +name+fileExtension)));
                //stream =new BufferedOutputStream(new FileOutputStream(new File(dstFile)));
                stream.write(bytes);
                message = "You successfully uploaded " + name + "!";
            } catch (Exception e) {
                message = "You failed to upload " + name + " => " + e.getMessage();
            } finally{
            	if (stream != null)try {stream.close();} catch (IOException e) {}
            }
       
       
	        srcFile= srcFilePath +name+fileExtension;
//	 		dstFile= dstFilePath +name+"_Dec"+fileExtension;
	 		dstFile= dstFilePath +name+fileExtension;
	 		//dstFile = "C:\\test\\4ad170d7-f8d0-427d-8bfe-608581e82aec_Dec.xls";
	 		
	 		logger.info("srcFile : "+srcFile);
	 		logger.info("dstFile : "+dstFile);
		
 			//문서복호화   0:성공   -36:원본파일이 비암호화문서 성공과 동일적용
 			int decRtn = DecFile(PropPath,keyFilePath,srcFile,dstFile);
		
			if(!(decRtn == 0 || decRtn == -36) ){
				if(decRtn == 1000){
					message = "[ERRROR] 문서보안 에러코드 : "+decRtn+" \n에러내용 : 원본파일이 없습니다";
				}else if(decRtn == 3000){
					message = "[ERRROR] 문서보안 에러코드 : "+decRtn+" \n에러내용 : 키 파일이 없습니다";
				}else{
					message = "[ERRROR] 문서보안 에러코드 : "+decRtn+" \n에러내용 : 복호화 실패하였습니다.";
				}
				logger.error(message);
                resultMap.put("message"  , message);
    			return resultMap;
			}
			
		} else {
            message = "You failed to upload " + name + " because the file was empty.";
        }
		
 		String [] sheetNames = service.getSheetName().split(",");

	    //3. sheet to memory
	    List<Map<String,Object>> mSheet = new ArrayList<Map<String,Object>>();
	    
	    
		 try{
	    	ExcelSheet[] sheets = (ExcelSheet[])ExcelUtil.loadExcelFile(dstFile); //복호화된 파일명
	    	
	        for (int i=0;i<sheets.length;i++){
	        	String[][] data = null;
	        	for(int j=0;j<sheetNames.length;j++){
	        		if (sheetNames[j].equals(sheets[i].getName())){
	        			int index = 0;
	        			if(fileExtension.equals(".xlsx")){
	        				int maxcolumn = 33;
							while (sheets[i].existsRowForXlsx(index)) {
								index++;
							}
							data = new String[index][maxcolumn];
							for(int row=0;row<index;row++){
								for(int col=0;col<maxcolumn;col++){
									data[row][col]=sheets[i].getCellStringForXlsx(row, col);
								}
							}
	        			}else{
	        				int maxcolumn = 28;
	        				while (sheets[i].existsRow(index)) {
								index++;
							}
							data = new String[index][maxcolumn];
							for(int row=0;row<index;row++){
								for(int col=0;col<maxcolumn;col++){
									data[row][col]=sheets[i].getCellString(row, col);
								}
							}
	        			}
						Map<String,Object> h = new HashMap<String,Object>();
						h.put("sheetName", sheets[i].getName());
						h.put("data", data);
						mSheet.add(h);
	        		}else{
	        			//sheet 명명규칙 오류
	        		}
	        	}
	        }
	    }catch(Exception e){
	    	message = "[ERRROR] 형식에 맞지않는 자료 입니다. ";
	    	logger.error(message+e.getMessage());
	    	resultMap.put("message"  , message);
			return resultMap;
	    }
		 
	    if(mSheet.size()==0){
	    	message = "[ERRROR] 유효한 시트명이 존재 하지 않습니다.";
	    	logger.error(message);
	    	resultMap.put("message"  , message);
			return resultMap;
	    }
	    
	  //0:중복시 저장하지 않음, 1:중복시 저장
  		String saveType = ServletRequestUtils.getStringParameter(request,"saveType", "");
  		if ("".equals(saveType)) {
  			message = "[ERRROR] 중복 시 저장타입을 선택해 주세요 ";
	    	logger.error(message);
	    	resultMap.put("message"  , message);
			return resultMap;
  		}
	    
	    List<HashMap<String,Object>> result = new ArrayList<HashMap<String,Object>>();
    	List<HashMap<String,Object>> list = null;
    	//String msg = "";
    	try {
	        for (int i=0;i<mSheet.size();i++){
	        	String[][] arrData = (String[][])mSheet.get(i).get("data");
	        	String sheetName = (String)mSheet.get(i).get("sheetName");
	        	//boolean isAccessable = false ;
	        	
	        	try{
	        		String eaisevrDstcd = ServletRequestUtils.getStringParameter(request,"eaisevrDstcd", "");
            		list = service.uploadFull(arrData,request,saveType,sheetName,eaisevrDstcd);
            	}catch(Throwable e){
            		list = new ArrayList<HashMap<String,Object>>();
            		HashMap<String,Object> row = new HashMap<String,Object>();
    				row.put("SHEETNAME" , sheetName);
    				row.put("LAYOUTNAME", "");
    				row.put("LAYOUTITEM", "");
    				row.put("RESULT"    , "X");
    				row.put("MESSAGE"   , e.getMessage());
    				list.add(row);
            	}
	        	result.addAll(list);
	        }
        
    	} catch (Throwable e) {
			message = e.getMessage();
		}
		resultMap.put("message"  , message);
		resultMap.put("rows"     , result);
		return resultMap;
	}
	/**
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping(value= "/onl/admin/rule/layoutExcelMan.file", params = "cmd=UPLOAD", method=RequestMethod.POST)
    public ModelAndView handleFileUpload(HttpServletRequest request,@RequestParam("file") MultipartFile file)throws Exception{
		HashMap resultMap = upload( request,  file);
		ModelAndView modelAndView = new ModelAndView("jsonView",resultMap);		
		return modelAndView;
	}
	/**
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping(value= "/onl/admin/rule/layoutExcelMan2.file", params = "cmd=UPLOAD", method=RequestMethod.POST)
    public String handleFileUpload2(HttpServletRequest request,@RequestParam("file") MultipartFile file)throws Exception{
		HashMap resultMap = upload( request,  file);
		request.setAttribute("message", resultMap.get("message"));
		request.setAttribute("rows", resultMap.get("rows") );
		return "common/jsonResult";
	}	
	
	
	@RequestMapping(value= "/onl/admin/rule/layoutExcelMan.json",params = "cmd=LIST_INIT_COMBO")
    public ModelAndView eaiSvcNameCombo( HttpServletRequest request,
            HttpServletResponse response) throws Exception {
    	
        List<ComboVo> listInoutTypeCd = comboService.getFromCode("INOUT_TYPE");//EAI서버구분코드
        
		
		Map resultMap = new HashMap();
		resultMap.put("inoutTypeRows"   , listInoutTypeCd);
		
		ModelAndView modelAndView = new ModelAndView("jsonView",resultMap);		
		return modelAndView;            
    } 
	
	public int DecFile(String prop,String keyFilePath,String srcFile,String dstFile) throws Exception{

//		SLDsFile sFile = new SLDsFile();
//
//		sFile.SettingPathForProperty(prop); 
//		
//		int retVal = sFile.CreateDecryptFileDAC (
//		keyFilePath,
//		"SECURITYDOMAIN",
//		srcFile,
//		dstFile);
//		logger.info( " CreateDecryptFileDAC [" + retVal + "]");
		int retVal=0;
		return retVal;
	}
	
	@RequestMapping(value="/onl/admin/rule/layoutExcelMan.json", params="cmd=TRANSACTION_EXCEL_IMPORT")
	public ModelAndView excelImport(HttpServletRequest request, String names, String saveType, String eaisevrDstcd) throws Exception {
		HashMap<String, Object> resultMap = new HashMap<String, Object>();
		String propPath 	= monitoringContext.getStringProperty(MonitoringContext.SOFTCAMP_PROP);
		String keyFilePath	= monitoringContext.getStringProperty(MonitoringContext.SOFTCAMP_KEY);
		
		try {
			List dataList = new ArrayList();
			if (StringUtils.isEmpty(propPath) || StringUtils.isEmpty(keyFilePath)) {
				throw new BizException("문서암호화 해제 프라퍼티를 확인해주세요.");
			}
			PropertyDAO propertyDAO =(PropertyDAO)DAOFactory.newInstance().create(PropertyDAO.class);
			PropGroupVO prop = propertyDAO.getProperties("CM_CONFIG");
			if (prop == null) {
				throw new BizException("프라퍼티 정보가 없습니다. - CM_CONFIG");
			}
			String rootPath = prop.getProperty("aurora.xls.path");
			if (names != null) {
				String[] arrNames = names.split(",");
				for (String name : arrNames) {
					int index = name.lastIndexOf(".");
					String fileName = name.substring(0, index);
					String fileExtension = name.substring(index + 1);
					String srcFile = rootPath + fileName +"."+ fileExtension;
					String decFile = rootPath + fileName + "_Dec" +"."+ fileExtension;
					int ret = DecFile(propPath, keyFilePath, srcFile, decFile);
					switch(ret) {
					case -36:	// 원본파일이 비암호화
					case 0:		// 암호화 성공
						logger.debug("복호화 성공: "+ decFile);
						break;
					case 1000:
						throw new BizException("원본파일이 없습니다.");
					case 3000:
						throw new BizException("키 파일이 없습니다.");
					default:
						throw new BizException("복호화 실패하였습니다.["+ ret + "]");
					}
					
					List<Map<String,Object>> sheetList = service.excelParsing(decFile, fileExtension);
					for (Map<String,Object> map : sheetList) {
						String sheetName = (String) map.get("sheetName");
						String[][] arrData = (String[][]) map.get("data");
						List list = null;
						try {
							list = service.uploadFull(arrData, request, saveType, sheetName, eaisevrDstcd);
						} catch (Throwable e) {
							list = new ArrayList<HashMap<String,Object>>();
							HashMap<String,Object> row = new HashMap<String,Object>();
							row.put("SHEETNAME" , sheetName);
							row.put("LAYOUTNAME", "");
							row.put("LAYOUTITEM", "");
							row.put("RESULT"    , "X");
							row.put("MESSAGE"   , e.getMessage());
							list.add(row);
						}
						dataList.addAll(list);
					}
					new File(srcFile).delete();
					new File(decFile).delete();
				}
			}
			resultMap.put("dataList", dataList);
		} catch (BizException be) {
			throw new Exception(be.getMessage());
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw new Exception(localeMessage.getString("errors.checklog"));
		}
		
		ModelAndView modelAndView = new ModelAndView("jsonView", resultMap);
		return modelAndView;
	}
}