package itn.let.utl.user.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import itn.com.cmm.EgovMessageSource;
import itn.com.cmm.service.FileVO;
import itn.com.cmm.util.StringUtil;
import itn.let.cop.bbs.service.BoardMaster;

/**
 *
 * 파일 체크에 대한 Util 클래스
 * @author 사업기술본부 조용준(ITN)
 * @since 2021.07.16
 * @version 1.0
 * @see
 *
 * <pre>
 * << 개정이력(Modification Information) >>
 *
 *   수정일      수정자           수정내용
 *  -------    --------    ---------------------------
 *   2021.07.16  조용준          최초 생성 *   
 *
 * </pre>
 */
@Service("checkFileUtil")
public class CheckFileUtil {

	private static final Logger LOGGER = LoggerFactory.getLogger(CheckBoardUtil.class);

	/** EgovMessageSource */
    @Resource(name="egovMessageSource")
    EgovMessageSource egovMessageSource;

    
    /**
     *     //게시판 첨부 파일 제약 조건 체크
     *
     * @param encrypt
     */  
    
	public boolean isPosblAtchFileMvWithBoardMaster(
			List<FileVO> fileList			
			, ModelAndView p_mv
			, int atchFileCnt			//기존에 파일이 있는 경우
			, String p_exts				//가능한 확장자를 받는다. |
			
			, BoardMaster boardMaster	//관리자 게시판 생성 정보
			) throws Exception {
		
		//LOGGER.debug("commonLoginUtil.isPosblAtchFileMv()");
		
		return this.p_isPosblAtchFileMvWithBoardMaster(fileList, boardMaster, p_mv, atchFileCnt, p_exts);
	}	
	
	/**
     *     //게시판 첨부 파일 제약 조건 체크
     *
     * @param encrypt
     */  
    
	public boolean isPosblAtchFileMvWithUserSetting(
			List<FileVO> fileList			
			, ModelAndView p_mv
			, int atchFileCnt			//기존에 파일이 있는 경우
			, String p_exts				//가능한 확장자를 받는다. |
			, int p_i_file_size
			, int p_i_file_count
			) throws Exception {
		
		//LOGGER.debug("commonLoginUtil.isPosblAtchFileMv()");
		
		return this.p_isPosblAtchFileMvWithUserSetting(fileList, p_mv, atchFileCnt, p_exts, p_i_file_size, p_i_file_count);
	}	
	
    /**
     *     //업로드된 text 파일에서 내용 추출하기
     *
     * @param encrypt
     */  
	//text 파일에서 추출하기
	public List<String> extractFromTxtFile(
			MultipartHttpServletRequest p_multiRequest
			, List<String> p_sb
			) throws Exception{
		
		return this.p_extractFromTxtFile(p_multiRequest, p_sb);	
	}
	
    /**
     *     //업로드된 excel 파일에서 내용 추출하기
     *
     * @param encrypt
     */  
	//excel 파일에서 추출하기(xls, xlsx)
	public List<String> extractFromExcelFile(
			MultipartHttpServletRequest p_multiRequest
			, List<String> p_sb
			) throws Exception{
		
		return this.p_extractFromExcelFile(p_multiRequest, p_sb);		
	}
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //
    //	private function
    //
    //	
    
	
    /**
     *     //게시판 첨부 파일 제약 조건으로 파일 체크
     *
     * @param encrypt
     */      
	private boolean p_isPosblAtchFileMvWithBoardMaster(
			List<FileVO> fileList
			, BoardMaster boardMaster
			, ModelAndView p_mv
			, int atchFileCnt			//기존에 파일이 있는 경우
			, String p_exts				//가능한 확장자를 받는다. |
			) throws Exception {
		
		boolean posblAtchFileFlag = true;
		
    	try {
    		LOGGER.debug("CheckFileUtil.isPosblAtchFileMvWithBoardMaster()");
    		

    		int fileCnt = 0;
    		long posblAtchFileSize = Long.parseLong(boardMaster.getPosblAtchFileSize()) * 1024 * 1024 ;
    		int posblAtchFileNumber = Integer.parseInt(boardMaster.getPosblAtchFileNumber());
    		//String bbsTyCode = boardMaster.getBbsTyCode();
    		String flashMessage = "";    		
    		boolean posblAtchFileSizeFlag = true; 
    		boolean posblAtchFileExtFlag = true; 
    		
    		String[] imgExts = p_exts.split("\\|");
    		
    		Iterator<?> iter = fileList.iterator();
    		while (iter.hasNext()) {
    			FileVO vo = (FileVO) iter.next();
    			long fileMg = Long.parseLong(vo.getFileMg());
    			String fileExt = vo.getFileExtsn();
    			
    			if (fileMg > posblAtchFileSize) posblAtchFileSizeFlag = false;
    			
    			//String[] imgExts = {"gif", "jpg", "bmp", "jpeg", "png"};
    			//String[] imgExts = {"xlsx", "xls", "zip", "hwp", "txt", "doc", "docx", "csv"};
    			
    			if (ArrayUtils.indexOf(imgExts, fileExt.toLowerCase()) == -1) posblAtchFileExtFlag = false;
    			
    			fileCnt++;
    		}
    		
    		if (!posblAtchFileExtFlag) {
    			for (int i=0;i<imgExts.length;i++) {
    				if (i==0) flashMessage += imgExts[i];
    				else flashMessage += ", " + imgExts[i];
    			}
    			flashMessage += " 형식의 확장자만 업로드 가능합니다." + "\\n";
    			posblAtchFileFlag = false;
    		}
    		if(!posblAtchFileSizeFlag) {
    			flashMessage += "파일사이즈가 초과되었습니다. 최대크기 " + posblAtchFileSize + "mb" + "\\n";
    			posblAtchFileFlag = false;
    		}
    		if ((fileCnt+atchFileCnt) > posblAtchFileNumber) {
    			flashMessage += "파일 개수가 초과되었습니다. 최대개수 " + posblAtchFileNumber + "개" + "\\n";
    			posblAtchFileFlag = false;
    		}
    		
    		if (!posblAtchFileFlag) p_mv.addObject("message", flashMessage);
        	
        } catch(IllegalArgumentException e) {
    		LOGGER.error("[IllegalArgumentException] Try/Catch...usingParameters Runing : "+ e.getMessage());
        } catch (Exception e) {
        	LOGGER.error("[" + e.getClass() +"] :" + e.getMessage());
        }   
    	
		return posblAtchFileFlag;
	}	
	

    /**
     *     //사용자의 조건으로 첨부 파일 제약 조건 체크
     *
     * @param encrypt
     */
	private boolean p_isPosblAtchFileMvWithUserSetting(
			List<FileVO> fileList			
			, ModelAndView p_mv
			, int atchFileCnt			//기존에 파일이 있는 경우
			
			, String p_exts				//가능한 확장자를 받는다. |
			, int p_i_file_size			//파일 제한 사이즈 
			, int p_i_file_count		//파일 제한 수량
			) throws Exception {
		
		boolean posblAtchFileFlag = true;
		
    	try {
    		LOGGER.debug("CheckFileUtil.isPosblAtchFileMvWithUserSetting()");
    		

    		int fileCnt = 0;
    		long posblAtchFileSize = p_i_file_size * 1024 * 1024 ;
    		int posblAtchFileNumber = p_i_file_count;
    		//String bbsTyCode = boardMaster.getBbsTyCode();
    		String flashMessage = "";    		
    		boolean posblAtchFileSizeFlag = true; 
    		boolean posblAtchFileExtFlag = true; 
    		
    		String[] imgExts = p_exts.split("\\|");
    		
    		Iterator<?> iter = fileList.iterator();
    		while (iter.hasNext()) {
    			FileVO vo = (FileVO) iter.next();
    			long fileMg = Long.parseLong(vo.getFileMg());
    			String fileExt = vo.getFileExtsn();
    			
    			if (fileMg > posblAtchFileSize) posblAtchFileSizeFlag = false;
    			
    			//String[] imgExts = {"gif", "jpg", "bmp", "jpeg", "png"};
    			//String[] imgExts = {"xlsx", "xls", "zip", "hwp", "txt", "doc", "docx", "csv"};
    			
    			if (ArrayUtils.indexOf(imgExts, fileExt.toLowerCase()) == -1) posblAtchFileExtFlag = false;
    			
    			fileCnt++;
    		}
    		
    		if (!posblAtchFileExtFlag) {
    			for (int i=0;i<imgExts.length;i++) {
    				if (i==0) flashMessage += imgExts[i];
    				else flashMessage += ", " + imgExts[i];
    			}
    			flashMessage += " 형식의 확장자만 업로드 가능합니다." + "\\n";
    			posblAtchFileFlag = false;
    		}
    		if(!posblAtchFileSizeFlag) {
    			flashMessage += "파일사이즈가 초과되었습니다. 최대크기 " + posblAtchFileSize + "mb" + "\\n";
    			posblAtchFileFlag = false;
    		}
    		if ((fileCnt+atchFileCnt) > posblAtchFileNumber) {
    			flashMessage += "파일 개수가 초과되었습니다. 최대개수 " + posblAtchFileNumber + "개" + "\\n";
    			posblAtchFileFlag = false;
    		}
    		
    		if (!posblAtchFileFlag) p_mv.addObject("message", flashMessage);
        	
        } catch(IllegalArgumentException e) {
    		LOGGER.error("[IllegalArgumentException] Try/Catch...usingParameters Runing : "+ e.getMessage());
        } catch (Exception e) {
        	LOGGER.error("[" + e.getClass() +"] :" + e.getMessage());
        }   
    	
		return posblAtchFileFlag;
	}
	
    /**
     *     //업로드된 text 파일에서 내용 추출하기
     *
     * @param encrypt
     */  
	//text 파일에서 추출하기
	private List<String> p_extractFromTxtFile(
			MultipartHttpServletRequest p_multiRequest
			, List<String> p_sb
			) throws Exception{
		
		LOGGER.debug("CheckFileUtil.extractFromTxtFile()");
		
		List<MultipartFile> files = (List<MultipartFile>) p_multiRequest.getFiles("file");		
		
		if(!files.isEmpty()) {
			
			if (files.get(0).getSize() > 0 
					&& files.get(0).getOriginalFilename().split("[.]")[1].indexOf("txt") > -1) {
				
				//Multi file to file 변환해주기
				File file = new File(files.get(0).getOriginalFilename());
				file.createNewFile();
				FileOutputStream fos = new FileOutputStream(file);
				fos.write(files.get(0).getBytes());
				fos.close();
				
				BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
				
				String line = null;
						
				while ((line = reader.readLine()) != null) {
					p_sb.add(line);											

				} // end while				
			}			
		}
		
		return p_sb;
	}
	
    /**
     *     //업로드된 excel 파일에서 내용 추출하기
     *
     * @param encrypt
     */  
	//excel 파일에서 추출하기(xls, xlsx)
	private List<String> p_extractFromExcelFile(
			MultipartHttpServletRequest p_multiRequest
			, List<String> p_sb
			) throws Exception{
		
		LOGGER.debug("CheckFileUtil.extractFromExcelFile()");
		
		List<MultipartFile> files = (List<MultipartFile>) p_multiRequest.getFiles("file");

		if(!files.isEmpty()) {
			
			if (files.get(0).getSize() > 0 
					&& (files.get(0).getContentType().indexOf("spreadsheetml") > -1
							|| files.get(0).getContentType().indexOf("ms-excel") > -1
							) 
					
					&&(
							files.get(0).getOriginalFilename().split("[.]")[1].indexOf("xlsx") > -1 
							|| files.get(0).getOriginalFilename().split("[.]")[1].indexOf("xls") > -1
							)
					) {
				
				String Ext = files.get(0).getOriginalFilename().split("[.]")[1];

		        String cellValue  = "";		        
		        
	            //엑셀 확장자에 따른 처리 로직 분리
				if(Ext.equals("xls")) {
					
					HSSFWorkbook workbook = new HSSFWorkbook(files.get(0).getInputStream());
				    HSSFSheet sheet = workbook.getSheetAt(0);	//첫번째 sheet 만 처리

		            for(int i=0; i< sheet.getLastRowNum(); i++){ //먼저 밸리데이션 체크(1줄은 생략)
		            	HSSFRow row = sheet.getRow(i); //열읽기
		            	
		            	cellValue	=	"";
		            	
		                for(int j = 0 ; j < row.getLastCellNum(); j++){ //행읽기(6행까지나 2행까지만 필요)		                	
		                	HSSFCell cell = row.getCell(j); //이름/핸드폰/변환1/변환2/변환3/변환4/변환5
		                	
		                	if(cell != null){
		                		switch(cell.getCellType()){ //숫자타임을 문자로 변환
		                			case  Cell.CELL_TYPE_NUMERIC:
		                			cell.setCellType(Cell.CELL_TYPE_STRING);
		                		}
		                		cellValue =  cellValue + StringUtil.getString(cell.getStringCellValue().trim()) + "\t";
		                    }
		                }
		                
		                p_sb.add(cellValue);
		            }
		            
				}else {	//확장자가 xlsx
					
					OPCPackage opcPackage = OPCPackage.open(files.get(0).getInputStream());
					XSSFWorkbook workbook = new XSSFWorkbook(opcPackage);
		            XSSFSheet sheet = workbook.getSheetAt(0); // 첫번째 시트 불러오기
		            opcPackage.close();
		            
		            for(int i=0; i< sheet.getLastRowNum(); i++){ //먼저 밸리데이션 체크(1줄은 생략)
		            	XSSFRow row = sheet.getRow(i); //열읽기
		            	
		            	cellValue	=	"";
		            	
		                for(int j = 0 ; j < row.getLastCellNum(); j++){ //행읽기(6행까지나 2행까지만 필요)		                	
		                	XSSFCell cell = row.getCell(j); //이름/핸드폰/변환1/변환2/변환3/변환4/변환5
		                	
		                	if(cell != null){
		                		switch(cell.getCellType()){ //숫자타임을 문자로 변환
		                			case  Cell.CELL_TYPE_NUMERIC:
		                			cell.setCellType(Cell.CELL_TYPE_STRING);
		                		}
		                		cellValue =  cellValue + StringUtil.getString(cell.getStringCellValue().trim()) + "\t";
		                    }		                	
		                }
		                
		                p_sb.add(cellValue);		                
		            }		            					
				}	//xlsx 처리 끝				
			}			
		}		
		
		return p_sb;
	}
	
}