package com.eactive.eai.adapter.ftp;

import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPFile;

import com.eactive.eai.adapter.socket.config.ConfigurationContext;
import com.eactive.eai.adapter.socket.service.SocketService;
import com.eactive.eai.batch.common.CalendarUtil;
import com.eactive.eai.batch.common.LogUtil;
import com.eactive.eai.batch.common.StringUtil;
import com.eactive.eai.batch.doc.BatchDoc;
import com.eactive.eai.batch.ftp.FTPUtil;
import com.eactive.eai.batch.running.BatchRunningJobManager;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.util.DatetimeUtil;
import com.eactive.eai.common.util.Logger;

// KED Findsystem 파일수신 ( SFTP )
// IP : 10.0.249.35 PORT : 22
// ID : kjbank PWD: kjbank2015
// 수신디렉터리 : /ftp_user/kjbank/test/senddata/findsystem
// 백업디렉터리 : ?
// 파일명: 
//   KED_20191015142047_20191015_H01_1_35766653888617_1_1_1058675080000.TIF
//   KEDFS_20191015142047_20191015_H06_1_35766653888617_1_1_1058675080000.TIF


public class FTPKF extends Transfer implements SocketService{

    private static final String PROP_GROUP_NAME_PREFIX = "TelegramInfo";
    private static final String REMOTE_PATH = "remote.path";
    private static final String BACKUP_PATH = "backup.path";
    private static final String FIN_EXT = "fin.ext";
    private static final String FILE_EXT = "file.ext";

	public void sendFile(BatchDoc batchDoc) throws Exception {
		throw new Exception("해당 Component 에 의한 FTP 송신이 구현되지 않았습니다.");
	}

	public void recvFile(BatchDoc batchDoc) throws Exception {
		logger.info("[FTPKF] ■ 대외기관→FEP 파일 수신 시작...... ");
		firstActivity = System.currentTimeMillis();
		setLastActivity();
		BatchRunningJobManager.getInstance().addRunningJobInfo( batchDoc.getBatchMsg().getHeader().getUUID(), this, batchDoc);
		
		try {
			String ipaddress = batchDoc.getBatchMsg().getHeader().getRemoteIP();
			int    port      = Integer.parseInt(batchDoc.getBatchMsg().getHeader().getPort());
			String userid    = batchDoc.getBatchMsg().getHeader().getUserID();
			String passwd    = batchDoc.getBatchMsg().getHeader().getUserPassword();
			
	        String propName = PROP_GROUP_NAME_PREFIX + "{" +
                    batchDoc.getBatchMsg().getHeader().getProcessCode() +
                    "_" +
                    batchDoc.getBatchMsg().getHeader().getInstitutionCode() + "}";
	        PropManager pmanager = PropManager.getInstance();

			String remotePath = pmanager.getProperties(propName).getProperty(REMOTE_PATH);
			if ( remotePath == null ){
				throw new Exception("해당 기관에 전송 경로가 지정되어 있지 않습니다. -propName:" + propName + "," + REMOTE_PATH);
			}
			if ( !remotePath.endsWith("/") )
				remotePath = remotePath + "/";

			String backupPath = pmanager.getProperties(propName).getProperty(BACKUP_PATH);
			if ( backupPath == null ){
				throw new Exception("해당 기관에 백업 경로가 지정되어 있지 않습니다. -propName:" + propName + "," + BACKUP_PATH);
			}
			
			String finExt = pmanager.getProperties(propName).getProperty(FIN_EXT);
			if (finExt == null){
				finExt = ".fin";
			}
			
			String fileExt = pmanager.getProperties(propName).getProperty(FILE_EXT);
			if (fileExt == null) {
				fileExt = ".tif";
			}

			logger.debug( "[FTPKF]FileName:" + batchDoc.getBatchMsg().getHeader().getFileName());
			String reqFileName = batchDoc.getBatchMsg().getHeader().getFileName();
			String baseDate = DatetimeUtil.getCurrentDate();
			if ( reqFileName != null && reqFileName.length() > 8 ){
				if ( DatetimeUtil.isRightDate(reqFileName.substring(reqFileName.length() - 8 )) ){
					baseDate = reqFileName.substring(reqFileName.length() - 8 );
					batchDoc.getBatchMsg().getHeader().setBaseDate(baseDate);
				}
			}

	        String authType = pmanager.getProperties(propName).getProperty(AUTH_TYPE);
	        if (StringUtils.isBlank(authType)) {
	        	authType = AUTH_TYPE_ID; // id
	        }
			remotePath = remotePath.replaceAll("#YYYYMMDD#", baseDate ); 
//			if ( !remotePath.endsWith("/") )
//				remotePath = remotePath + "/";
	        
			backupPath = backupPath.replaceAll("#YYYYMMDD#", baseDate ); 
			if ( !backupPath.endsWith("/") )
				backupPath = backupPath + "/";

			//20220712 
			String connTimeoutStr = pmanager.getProperties(propName).getProperty(CONNECTION_TIMEOUT, "10");
			int connTimeout = Integer.parseInt(connTimeoutStr);
			String setTimeoutStr = pmanager.getProperties(propName).getProperty(READ_TIMEOUT, "10");
			int setTimeout =  Integer.parseInt(setTimeoutStr);			
			String bandWidthLimit = pmanager.getProperties(propName).getProperty(BADNWIDTH, "0");
			bandWidthLimit = bandWidthLimit.replace("K", "000").replace("M", "000000").replaceAll(",", "");
			int bandWidth = Integer.parseInt(bandWidthLimit);
			
			FTPFile[] list = null;
            try {
    			list = FTPUtil.listFiles(ipaddress, port, userid, passwd, remotePath, null, true, batchDoc.getLogger(Logger.LOGGER_ADAPTER), authType);
    			
    			// .fin 파일에서 원본 파일을 찾기 위해서 
    			Map<String, FTPFile> fileMap = new HashMap<String, FTPFile>();
    			for (int i = 0; i < list.length; i++) {
    				fileMap.put(list[i].getName(), list[i]);
    			}
    			
    			for (int i = 0 ; i < list.length; i++){
    				FTPFile file = list[i];
    				if ( file.getName().endsWith(finExt) ){
    					String finFileName = file.getName();
    					
    					// a.fin을 a.tif로 변경
    					String recvFileName = finFileName.substring(0, finFileName.length() - finExt.length());
	    				recvFileName += fileExt;
    					FTPFile recvFtpFile = fileMap.get(recvFileName);
    					
    					if (recvFtpFile == null) {
	    					throw new Exception(file.getName() + " 파일에 해당하는 원본 파일 [" + recvFileName + "] 이 없습니다.");
    					}
    					
    					batchDoc.getBatchMsg().getHeader().setFileSize(recvFtpFile.getSize());
    					batchDoc.getBatchMsg().getHeader().setTotRecCnt(1);
    					batchDoc.getBatchMsg().getBody().setPhaseStartTime(CalendarUtil.getCurrentTimeNoDash());
    					batchDoc.getBatchMsg().getHeader().setFileName(recvFtpFile.getName());
    					LogUtil.setLogFileStart(batchDoc);

						//FTPUtil.retrieve(ipaddress, port, userid, passwd, remotePath + recvFileName, batchDoc.getBatchMsg().getHeader().getFilePath(), true, batchDoc.getLogger(ElinkLogger.LOGGER_ADAPTER));
						FTPUtil.retrieve(batchDoc, ipaddress, port, userid, passwd, remotePath, recvFileName, batchDoc.getBatchMsg().getHeader().getFilePath(),
    							connTimeout, setTimeout, true, bandWidth, batchDoc.getLogger(Logger.LOGGER_ADAPTER), authType);
						//batchDoc.getBatchMsg().getHeader().setFileSize(fileSize);
    					batchDoc.getBatchMsg().getHeader().setTotRecCnt(1);
						String recvFile = batchDoc.getBatchMsg().getHeader().getFilePath() + File.separator +  recvFileName;
    					File rcvRealFile = new File( recvFile );
    					File rcvChkFile = new File(StringUtil.realToRootDir(recvFile));
    					
    					try {
    						File rcvArchFile = new File(StringUtil.realToArchDir(recvFile));
    						if (rcvRealFile.exists() && rcvRealFile.length() == batchDoc.getBatchMsg().getHeader().getFileSize() ) {
				                //setFileHeaderAndTrailer(batchDoc, rcvRealFile);
    							rcvRealFile.renameTo(rcvArchFile);
    							rcvChkFile.createNewFile();
    						} else {
				            	throw new Exception("파일수신에 실패하였습니다." + recvFileName);
    						}
    					
	    					// 원본 파일 백업
	    					try {
				            	FTPUtil.renameWithMkdirs(ipaddress, port, userid, passwd, remotePath + recvFileName, backupPath, recvFileName, true, batchDoc.getLogger(Logger.LOGGER_ADAPTER), authType);
	    					} catch (Exception e) {
				            	logger.error("파일 백업에 실패하였습니다." + recvFileName, e);
				            	throw new Exception("파일 백업에 실패하였습니다.");
	    					}
	    					
	    					// .fin 파일 백업
	    					try {
				            	FTPUtil.rename(ipaddress, port, userid, passwd, remotePath + file.getName(), backupPath + file.getName(), true, batchDoc.getLogger(Logger.LOGGER_ADAPTER), authType);
	    					} catch (Exception e) {
				            	logger.error(".fin 파일 백업에 실패하였습니다." + file.getName(), e);
				            	throw new Exception(".fin 파일 백업에 실패하였습니다.");
	    					}
	    					//File 종료시간 설정
	    					batchDoc.getBatchMsg().getBody().setPhaseEndTime(CalendarUtil.getCurrentTimeNoDash());
	    					LogUtil.setLogFileEnd(batchDoc);
    					} catch (Exception e) {
    						throw e;
    					}
    				}
    			}
    			
            }catch ( Exception e ){
            	if ( e.getMessage() != null && !e.getMessage().contains("No such file"))
            		throw e;
            }
        } catch(Exception ex) {
            String[] msgArgs = new String[1];
            msgArgs[0] = batchDoc.getBatchMsg().getHeader().getProcessCode();
            String errCode = "BECEAIFJI002";
            String errMsg = ExceptionUtil.getErrorCode (ex, errCode, msgArgs);
            batchDoc.getBatchMsg().getBody().setErrorMsg(errMsg);
            LogUtil.setErrorLog(batchDoc, ex.getMessage());
            logger.error( errMsg, ex );
            throw ex;
		} finally {
			this.disconnect();
        }
		logger.info("[FTPKF] ■ VAN사 → FEP 파일 수신 완료.");		
	}

	@Override
	public void shutdown() {
		
	}

	@Override
	public Socket getCurrentSocket() {
		return null;
	}

	@Override
	public boolean connect() {
		return false;
	}

	@Override
	public ConfigurationContext getContext() {
		return null;
	}

	@Override
	public void setControl(Object control) {
		
	}

	@Override
	public void notifyMessage() {
		
	}

	@Override
	public boolean idle(long timeout) {
		return false;
	}

	@Override
	public int getCurrentState() {
		return 0;
	}

	@Override
	public boolean isConnected() throws IOException {
		return false;
	}

	@Override
	public boolean isActive() {
		return false;
	}

	@Override
	public void checkActivity() {
		
	}

	@Override
	public String getRemoteIPAddress() {
		return null;
	}

	@Override
	public void setLastActivity() {
		lastActivity = System.currentTimeMillis();
	}

	@Override
	public long getFirstActivity() {
		return firstActivity;
	}

	@Override
	public long getLastActivity() {
		return lastActivity;
	}
}