package cmm.service.impl;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
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 cmm.service.CmmFileService;
import cmm.service.FileDetailVO;
import cmm.service.FileManagementVO;
import cmm.service.FileMasterVO;
import cmm.util.DateUtil;
import cmm.util.FileUtil;
import egovframework.rte.fdl.cmmn.EgovAbstractServiceImpl;
import egovframework.rte.fdl.cmmn.exception.EgovBizException;
import egovframework.rte.fdl.cmmn.exception.FdlException;
import egovframework.rte.fdl.idgnr.EgovIdGnrService;
import egovframework.rte.fdl.property.EgovPropertyService;

@Service("cmmFileService")
public class CmmFileServiceImpl extends EgovAbstractServiceImpl implements CmmFileService {

	@Resource(name = "cmmFileDAO")
	private CmmFileDAO cmmFileDAO;
	
//	@Resource(name = "egovFileIdGnrService")
//	private EgovIdGnrService idgenService;
	
    /** EgovPropertyService */
    @Resource(name = "propertiesService")
    protected EgovPropertyService propertiesService;
	
	private static final Logger LOGGER = LoggerFactory.getLogger(CmmFileServiceImpl.class);
	

	@SuppressWarnings("unused")
	public String uploadFile(HttpServletRequest request, FileManagementVO fileManagementVO) throws IOException, EgovBizException {
		MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request;
		
		
		final Map<String, MultipartFile> files = multiRequest.getFileMap();
		
		String fileMstNo = null;
		String path = propertiesService.getString("file.upload.path") + DateUtil.getNowString(DateUtil.DATE_DB_FORMAT)+"/";
		File file = new File(path);
		file.setExecutable(false, true);
		file.setReadable(true);
		file.setWritable(false,true);
		if (!file.exists()) {
			file.mkdirs();
		}
		List<MultipartFile> fileList = multiRequest.getFiles(fileManagementVO.getFdFile());
		
		int index = fileManagementVO.getIndex();
		if (fileList == null) {
			LOGGER.debug("No file attached.");
			return null;
		}

		LOGGER.debug("CHANG CHECK POINT FILE LIST : " + fileList + ", fdFile : " + fileManagementVO.getFdFile());
		if (StringUtils.isNotEmpty(fileManagementVO.getFdMstNo())) {
			String[] fileMstNoArr = multiRequest.getParameterValues(fileManagementVO.getFdMstNo());
			if (fileMstNoArr != null) {
				if (StringUtils.isNotEmpty(fileMstNoArr[index])) {
					fileMstNo = fileMstNoArr[index];
				}
			}
		}
		if (fileManagementVO.isMulti() == false) {
			String ctrlStr = null;
			String title = null;
			if (fileManagementVO.getFdCtrl() != null) {
				ctrlStr = multiRequest.getParameterValues(fileManagementVO.getFdCtrl())[index];
			}
			if (fileManagementVO.getFdTitle() != null) {
				title = multiRequest.getParameterValues(fileManagementVO.getFdTitle())[index];
			}
			if (FileUtil.ORDER_FLAG_DELETE.equals(ctrlStr)) {
				FileDetailVO fileDetailVO = cmmFileDAO.selectFileDetailFirst(fileMstNo);
				if (fileDetailVO != null) {
					this.deleteFile(fileDetailVO.getFileStreCours(), fileDetailVO.getStreFileNm());
					this.deleteFileDetail(fileDetailVO);
				}
			} else if (FileUtil.ORDER_FLAG_RETRIEVE.equals(ctrlStr)) {
			} else {
				FileDetailVO fileDetailVONew = null;
				if (fileList.size() > 0) {
					MultipartFile multipartFile = fileList.get(index);
					fileDetailVONew = this.saveFile(multipartFile, fileManagementVO, fileMstNo, path, null);
				}
				if (fileDetailVONew != null) {
					fileMstNo = fileDetailVONew.getAtchFileId();
					FileDetailVO fileDetailVO = cmmFileDAO.selectFileDetailFirst(fileMstNo);
					if (fileDetailVO != null) {
						this.deleteFile(fileDetailVO.getFileStreCours(), fileDetailVO.getStreFileNm());
						fileDetailVONew.setFileSn(fileDetailVO.getFileSn());
						this.alternateFileDetail(fileDetailVONew);
					} else {
						//fileDetailVONew.setAtchFileId(idgenService.getNextStringId());
						int newMaxFileSN = cmmFileDAO.getMaxFileSN(fileDetailVONew);
						fileDetailVONew.setFileSn(Integer.toString(newMaxFileSN - 1));
						
						this.createNewFileDetail(fileDetailVONew);
					}
				}
			}
		} else {
			for (int i = 0; i < fileList.size(); i++) {
				String ctrlStr = multiRequest.getParameterValues(fileManagementVO.getFdCtrl())[i];
				String title = null;
				String fileDtlNo = null;
				if (fileManagementVO.getFdTitle() != null) {
					title = multiRequest.getParameterValues(fileManagementVO.getFdTitle())[i];
				}
				if (fileManagementVO.getFdDtlNo() != null) {
					fileDtlNo = multiRequest.getParameterValues(fileManagementVO.getFdDtlNo())[i];
				}
				if (FileUtil.ORDER_FLAG_INSERT.equals(ctrlStr)) {
					MultipartFile multipartFile = fileList.get(i);
					FileDetailVO fileDetailVO = this.saveFile(multipartFile, fileManagementVO, fileMstNo, path, title);
					if (fileDetailVO == null) {
						continue;
					}
					fileMstNo = fileDetailVO.getAtchFileId();
					int newMaxFileSN = cmmFileDAO.getMaxFileSN(fileDetailVO);
					fileDetailVO.setFileSn(Integer.toString(newMaxFileSN));
					this.createNewFileDetail(fileDetailVO);
				} else if (FileUtil.ORDER_FLAG_UPDATE.equals(ctrlStr)) {
					MultipartFile multipartFile = fileList.get(i);
					FileDetailVO fileDetailVONew = this.saveFile(multipartFile, fileManagementVO, fileMstNo, path, title);
					FileDetailVO fileDetailVO = null;
					if (fileDetailVONew == null) {
						
					} else {
						fileMstNo = fileDetailVONew.getAtchFileId();
						fileDetailVONew.setFileSn(fileDtlNo);
						fileDetailVO = cmmFileDAO.selectFileDetail(fileDetailVONew);
						if (fileDetailVO != null) {
							this.deleteFile(fileDetailVO.getFileStreCours(), fileDetailVO.getStreFileNm());
							fileDetailVONew.setAtchFileId(fileDetailVO.getAtchFileId());
							this.alternateFileDetail(fileDetailVONew);
						} else {
							int newMaxFileSN = cmmFileDAO.getMaxFileSN(fileDetailVONew);
							fileDetailVONew.setFileSn(Integer.toString(newMaxFileSN - 1));
							this.createNewFileDetail(fileDetailVONew);
						}
					}
				} else if (FileUtil.ORDER_FLAG_DELETE.equals(ctrlStr)) {
					FileDetailVO fileDetailVO = new FileDetailVO();
					fileDetailVO.setAtchFileId(fileMstNo);
					fileDetailVO.setFileSn(fileDtlNo);
					fileDetailVO = cmmFileDAO.selectFileDetail(fileDetailVO);
					if(fileManagementVO.isSaveToDisk()) {
						this.deleteFile(fileDetailVO.getFileStreCours(), fileDetailVO.getStreFileNm());
					}
					this.deleteFileDetail(fileDetailVO);
				}
			}
		}
		return fileMstNo;
	}
	public String uploadFileOneAttMulti(HttpServletRequest request, FileManagementVO fileManagementVO, int cnt) throws IOException, EgovBizException {
		MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request;
		
		String fileMstNo = null;
		String fileReturnMstNo = null;
		String path = propertiesService.getString("file.upload.path") + DateUtil.getNowString(DateUtil.DATE_DB_FORMAT)+"/";
		File file = new File(path);
		file.setExecutable(false, true);
		file.setReadable(true);
		file.setWritable(false,true);
		if (!file.exists()) {
			file.mkdirs();
		}
		
		for(int i = 1; i <= cnt; i++){
			MultipartFile multipartFile = multiRequest.getFile("atchFile0"+i);

			String ctrlStr = multiRequest.getParameter("atchCtrl0"+i);
			String fileDtlNo = null;
			fileDtlNo = multiRequest.getParameter("atchDtlNo0"+i);
			if(multipartFile != null){
				if((fileManagementVO.getFdMstNo() != null) && (!"".equals(fileManagementVO.getFdMstNo()))){
					fileMstNo = fileManagementVO.getFdMstNo();
				}
				fileMstNo = uploadFileOneAttMulti(multipartFile, fileManagementVO, i, fileMstNo, ctrlStr, fileDtlNo, path);
				
				if(!"".equals(fileMstNo)){
					fileReturnMstNo = fileMstNo;
				}
				
			}
		}
		
		return fileReturnMstNo;
	}
	
	public String uploadFileOneAttMulti(MultipartFile multipartFile, FileManagementVO fileManagementVO, int fileSn, String fileMstNo, String ctrlStr,  String fileDtlNo, String path) throws IOException, EgovBizException {
		
		String fileReturnMstNo = fileMstNo;
		if (FileUtil.ORDER_FLAG_DELETE.equals(ctrlStr)) {
			FileDetailVO fileDetailVONew = new FileDetailVO();
			fileDetailVONew.setFileSn(Integer.toString(fileSn));
			fileDetailVONew.setAtchFileId(fileReturnMstNo);
			FileDetailVO fileDetailVO = cmmFileDAO.selectFileDetail(fileDetailVONew);
			if (fileDetailVO != null) {
				this.deleteFile(fileDetailVO.getFileStreCours(), fileDetailVO.getStreFileNm());
				this.deleteFileDetail(fileDetailVO);
			}
		} else if (FileUtil.ORDER_FLAG_RETRIEVE.equals(ctrlStr)) {
		} else {
			FileDetailVO fileDetailVONew = null;
			fileDetailVONew = this.saveFile(multipartFile, fileManagementVO, fileReturnMstNo, path, null);
			if (fileDetailVONew != null) {
				fileDetailVONew.setFileSn(Integer.toString(fileSn));
				FileDetailVO fileDetailVO = cmmFileDAO.selectFileDetail(fileDetailVONew);
				if (fileDetailVO != null) {
					this.deleteFile(fileDetailVO.getFileStreCours(), fileDetailVO.getStreFileNm());
					fileDetailVONew.setFileSn(Integer.toString(fileSn));
					this.alternateFileDetail(fileDetailVONew);
				} else {
					fileReturnMstNo = fileDetailVONew.getAtchFileId();
					fileDetailVONew.setFileSn(Integer.toString(fileSn));
					this.createNewFileDetail(fileDetailVONew);
				}
			}
		}
		return fileReturnMstNo;
	}
	private boolean deleteFile(String filePath, String fileNm) {
		File file;
		try {
			file = new File(filePath, fileNm);
			if (file.exists()) {
				file.delete();
			}
		} catch(NullPointerException ex) {
			LOGGER.error("Error in deleteFile()" , ex);
			return false;
		} catch(SecurityException ex) {
			LOGGER.error("Error in deleteFile()" , ex);
			return false;
		}
		
		return true;
	}

	private FileDetailVO saveFile(MultipartFile multipartFile, FileManagementVO fileManagementVO, String fileMstNo, String path, String title) throws IOException, EgovBizException {
		FileMasterVO fileMasterVO = null;
		String saveFilename = "";
		@SuppressWarnings("unused")
		File file = null;
		String filename = multipartFile.getOriginalFilename();
		String filepath = "";
		
		if (StringUtils.isEmpty(filename)) {
			return null;
		}
		
		String fileExt = filename.substring(filename.lastIndexOf(".") + 1);
		
		if (fileManagementVO.isSaveToDisk()) {
			SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
			String today = formatter.format(new java.util.Date());
			saveFilename = today + UUID.randomUUID().toString() +"."+ fileExt;
			filepath = path;
			LOGGER.debug("["+ fileManagementVO.getFdFile() +"]: "+ multipartFile.getName()
					+", "+ filename
					+", "+ saveFilename
				);
			
			multipartFile.transferTo(new File(path, saveFilename));
		}
		
		if (fileMstNo == null) {
			fileMasterVO = this.createNewFileMaster(fileManagementVO);
			fileMstNo = fileMasterVO.getAtchFileId();
		} else {
			BigDecimal cnt = cmmFileDAO.selectFileMasterCount(fileMstNo);
			if (cnt.equals(BigDecimal.valueOf(0))) {
				fileMasterVO = this.createNewFileMaster(fileManagementVO);
				fileMstNo = fileMasterVO.getAtchFileId();
			}
		}
		
		FileDetailVO fileDetailVO = new FileDetailVO();
		fileDetailVO.setAtchFileId(fileMstNo);
		fileDetailVO.setOrignlFileNm(filename);
		fileDetailVO.setFileStreCours(filepath);
		fileDetailVO.setStreFileNm(saveFilename);
		fileDetailVO.setFileExtsn(fileExt);
		fileDetailVO.setFileSize(BigDecimal.valueOf(multipartFile.getSize()));

		if (fileManagementVO.isSaveToDisk() == false) {
			fileDetailVO.setFileData(multipartFile.getBytes());
		}
		
		return fileDetailVO;
	}
	
	public boolean deleteAllFileDetailAndMaster(String fileMstNo) throws IOException, EgovBizException {
		
		if (fileMstNo == null) {
			return false;
		}
		List<FileDetailVO> fileDetailVOList = cmmFileDAO.selectFileDetailList(fileMstNo);
		for (FileDetailVO fileDetailVO : fileDetailVOList) {
			this.deleteFile(fileDetailVO.getFileStreCours(), fileDetailVO.getStreFileNm());
			this.deleteFileDetail(fileDetailVO);
		}
		this.deleteFileMaster(fileMstNo);
		
		return true;
	}
	
	private void deleteFileMaster(String fileMstNo) throws IOException, EgovBizException {
		cmmFileDAO.deleteFileMaster(fileMstNo);
	}
	
	private void deleteFileDetail(FileDetailVO fileDetailVO) throws IOException, EgovBizException {
		cmmFileDAO.deleteFileDetail(fileDetailVO);
	}
	
	private void alternateFileDetail(FileDetailVO fileDetailVO) throws IOException, EgovBizException {
		cmmFileDAO.alternateFileDetail(fileDetailVO);
	}
	
	private void createNewFileDetail(FileDetailVO fileDetailVO) throws IOException, EgovBizException {
		cmmFileDAO.insertFileDetail(fileDetailVO);
	}

	private FileMasterVO createNewFileMaster(FileManagementVO fileManagementVO) throws IOException, EgovBizException {
		FileMasterVO fileMasterVO = new FileMasterVO();
//		try {
//			fileMasterVO.setAtchFileId(idgenService.getNextStringId());
//		} catch (FdlException e) {
//			LOGGER.error("fail in createNewFileMaster() getNextStringId()", e);
//		}
		cmmFileDAO.insertFileMaster(fileMasterVO);
		return fileMasterVO;
	}
	
	public List<FileDetailVO> selectFileDetailList(String atchFileId) throws IOException, EgovBizException {
		if (atchFileId == null) {
			return null;
		}
		return cmmFileDAO.selectFileDetailList(atchFileId);
	}
	public FileDetailVO selectFileDetail(FileDetailVO fileDetailVOParam) throws IOException, EgovBizException {
		return cmmFileDAO.selectFileDetail(fileDetailVOParam);
	}
	public BigDecimal selectFileDetailCount(String fileMstNo) throws IOException, EgovBizException {
		return cmmFileDAO.selectFileDetailCount(fileMstNo);
	}
	public FileDetailVO selectFileDetailFirst(String atchFileId) throws IOException, EgovBizException {
		if (atchFileId == null) {
			return null;
		}
		return cmmFileDAO.selectFileDetailFirst(atchFileId);
	}
	public List<FileDetailVO> selectIconFileDownLoad(String atchFileId) throws IOException, EgovBizException {
		return cmmFileDAO.selectIconFileDownLoad(atchFileId);
	}
}
