/**********************************************************************************
 * 프로그램명 : remit_excepted_list.java 프로그램설명 : 정해준 디렉토리 내의 디렉토리이름과 파일 이름순으로 정렬 작 성 자 : 강 원 중 작 성 일 : 2002/3/31 최신변경일 :
 * 2002. 6.29 다운 받은곳 : http://cpost.go.kr/shop/shop/way-board.php?db=sq&j=dn&number=57
 ***********************************************************************************/

package kr.co.kihyun.io;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.channels.FileChannel;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import kr.co.kihyun.beans.user.HttpSSOLogin;
import kr.co.kihyun.db.CommonDBManager;
import kr.co.kihyun.lang.Encoder;

import kr.co.kihyun.lang.MString;
import kr.co.kihyun.moumi.Moumi;
import kr.co.kihyun.moumi.MoumiConfig;
import kr.co.kihyun.text.html.GetAttachFileName;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FileUtil {
	private static final Logger LOG = LoggerFactory.getLogger(FileUtil.class);

	public static String getName(String filename, String appStr) {
     /*   String tmpDot = Integer.toString(filename.lastIndexOf("."));
        String dumy = ".";
        int indexOfdot;
        if(tmpDot.equals("")){
           indexOfdot = filename.lastIndexOf(dumy);
        }else{
           indexOfdot = filename.lastIndexOf(tmpDot);
        }*/
		int indexOfdot = filename.lastIndexOf(".");//파일이름중에 . 있는지 없는지 확인
    	return filename.substring(0, indexOfdot) + "_" + appStr + filename.substring(indexOfdot);
	}

	public static String getName(String filename, String deptID, String userID, String docID, String appStr) {
       /*  String tmpDot = Integer.toString(filename.lastIndexOf("."));
         String dumy = ".";
        int indexOfdot;
        if(tmpDot.equals("")){
           indexOfdot = filename.lastIndexOf(dumy);
        }else{
           indexOfdot = filename.lastIndexOf(tmpDot);
        }*/
		int indexOfdot = filename.lastIndexOf(".");//파일이름중에 . 있는지 없는지 확인
		return deptID + "_" + userID + "_" + docID + "_" + appStr + filename.substring(indexOfdot);
	}

	public static String getFirstName(String filename) {
       /*  String tmpDot = Integer.toString(filename.lastIndexOf("."));
         String dumy = ".";
        int indexOfdot;
        if(tmpDot.equals("")){
           indexOfdot = filename.lastIndexOf(dumy);
        }else{
           indexOfdot = filename.lastIndexOf(tmpDot);
        }*/
		int indexOfdot = filename.lastIndexOf(".");
		return filename.substring(0, indexOfdot);
	}

	public static String getExtName(String filename) {
       /*  String tmpDot = Integer.toString(filename.lastIndexOf("."));
         String dumy = ".";
        int indexOfdot;
        if(tmpDot.equals("")){
           indexOfdot = filename.lastIndexOf(dumy);
        }else{
           indexOfdot = filename.lastIndexOf(tmpDot);
        }*/
		int indexOfdot = filename.lastIndexOf(".");
		return filename.substring(indexOfdot);
	}

	public static void putInFiles(String svrFilenames, IUploadable uploadable) throws IOException {
                 putUpFiles(svrFilenames,uploadable); //디비에 파일을 인풋시킨다.


	}

    public static void putUpFiles(String svrFilenames, IUploadable uploadable) throws IOException {

		    if (MString.isNull(svrFilenames))
		    	return;
                    File sourceDir = new File(MoumiConfig.getFileDirectory().getPath());
		    for (String fileName : svrFilenames.split(";")) {
		    if (!MString.isNull(fileName)) {
                    File sourceFile = new File(sourceDir, fileName);
//                    System.out.println("sourceFile.exists() --- "+sourceFile.exists() + "\nuploadable.getAttachments().get(fileName) --- " +uploadable.getAttachments().get(fileName));
                    if (!sourceFile.exists())
                    continue;

                    //14.부적절한 자원 해제(FileInputStream/FileOutputStream)_CWE-404 : Update by KWON,HAN
                    //FileInputStream fis = new FileInputStream(sourceFile);
                    //byte[] content = new byte[(int) sourceFile.length()];
                    //Byte[] contentObj = new Byte[content.length];
                    //fis.read(content);//파일의 내용을 읽어온다.
                    //for (int i = 0; i < content.length; i++)
                    //contentObj[i] = content[i];
                    //uploadable.addAttachment(fileName, Arrays.asList(contentObj));
                    //fis.close();//파일실행을 끊어줌.
                    //
                FileInputStream fis = null;
                try {
                    fis = new FileInputStream(sourceFile);
                    byte[] content = new byte[(int) sourceFile.length()];
                    Byte[] contentObj = new Byte[content.length];
                    fis.read(content);//파일의 내용을 읽어온다.
                    for (int i = 0; i < content.length; i++)
                    contentObj[i] = content[i];
                    uploadable.addAttachment(fileName, Arrays.asList(contentObj));
                } catch (IOException e) {
                     e.printStackTrace();
                } finally {
                    fis.close(); //파일실행을 끊어줌.// 예외 발생 여부와 상관없이 자원 해제
                }
                //===================================================================================
        }
	  }
	}


    //20170821 첨부파일 저장을 위해 추가 by wonseok Lee
	public static void putInFiles(String svrFilenames, IUploadable uploadable, MultipartRequest multi) throws IOException {
                 putUpFiles(svrFilenames,uploadable, multi); //디비에 파일을 인풋시킨다.
	}

    public static void putUpFiles(String svrFilenames, IUploadable uploadable,  MultipartRequest multi) throws IOException {

		    if (MString.isNull(svrFilenames))
		    	return;
            File sourceDir = null;

            String docID = "";
            String modeChk = MString.checkNull(multi.getParameter("modify"));
            String reportID = MString.checkNull(multi.getParameter("reportID"));
            String dtID = MString.checkNull(HttpSSOLogin.getDeptID(multi));

            if(modeChk.equals("modify")){
            	docID = MString.checkNull(multi.getParameter("docId"));
            }
            else {
            	docID = MString.checkNull(multi.getParameter("repDocID"));
            }

            sourceDir = new File(MoumiConfig.getFileDirectory()+"/"+docID+"/"+reportID+"/"+dtID+"/");

		    for (String fileName : svrFilenames.split(";")) {
		    if (!MString.isNull(fileName)) {
                    File sourceFile = new File(sourceDir, fileName);
                    if (!sourceFile.exists())
                    continue;
//System.out.print("sourceFile.exists["+fileName+"]\n");

                    //14.부적절한 자원 해제(FileInputStream/FileOutputStream)_CWE-404 : Update by KWON,HAN
                    //FileInputStream fis = new FileInputStream(sourceFile);
                    //byte[] content = new byte[(int) sourceFile.length()];
                    //Byte[] contentObj = new Byte[content.length];
                    //fis.read(content);//파일의 내용을 읽어온다.
                    //for (int i = 0; i < content.length; i++)
                    //contentObj[i] = content[i];
                    //uploadable.addAttachment(fileName, Arrays.asList(contentObj));
                    //fis.close();//파일실행을 끊어줌.
                    //
                FileInputStream fis = null;
                try {
                    fis = new FileInputStream(sourceFile);


                    byte[] content = new byte[(int) sourceFile.length()];
                    Byte[] contentObj = new Byte[content.length];
                    fis.read(content);//파일의 내용을 읽어온다.

                    for (int i = 0; i < content.length; i++)
                    contentObj[i] = content[i];

                    uploadable.addAttachment(fileName, Arrays.asList(contentObj));
                } catch (IOException e) {
                     e.printStackTrace();
                } finally {
                    fis.close(); //파일실행을 끊어줌.// 예외 발생 여부와 상관없이 자원 해제
                }
                //===================================================================================
        }
	  }
	}

    public static void delUpFiles(String svrFilenames, IUploadable uploadable) throws IOException {
        try {

            if (MString.isNull(svrFilenames))
                return;

            //9.디렉토리 경로 조작(프로퍼티로딩)_CWE-22/23 : Add by KWON,HAN
            if(svrFilenames.contains("..") || svrFilenames. contains("/")) { // 특수문자열 검증
                LOG.debug("9.디렉토리 경로 조작(프로퍼티로딩)_CWE-22/23 : Test OK {}", svrFilenames);
                return;
            }
            //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

            File sourceDir = new File(MoumiConfig.getFileDirectory().getPath());
            for (String fileName : svrFilenames.split(";")) {

                File f = new File(sourceDir,fileName);

                if (f.exists() && f.isFile())
                    f.delete();
                //System.out.print("DEL FileUtil Page File Name: "+svrFilenames+"  Full Path and File Name: "+f+"\n");
            }
        } catch (Exception e) {
            //34.오류메세지를 통한 정보 노출(toString)_CWE-209 : Update by YOUNGJUN,CHO
            //System.out.println(e.toString());
            LOG.error("\nFileUtil delUpFiles Exception - {}", e.toString());
            //================================================
        }
    }
    public static String getGlobalBoardAttachmentsPath(){
    	return MoumiConfig.getFileDirectory().getPath()+"/boardattachment/";
    }
    //게시판 첨부파일 가져오기
    public static String getBoardAttachFileUrl(Long id,String fileName,HttpServletRequest req){
    	ArrayList<String> fns= getBoardAttachmentsFileNames(id,req,false);
    	for (String fn : fns) {
			if(fn.equals(fileName)){
				String opath= getGlobalBoardAttachmentsPath()+id+"/files/"+fn;
				String tpath="/tempfile/board/"+UUID.randomUUID()+"/";
				String rtpath=req.getSession().getServletContext().getRealPath(tpath)+"/";
				File tfile=new File(rtpath);
				try {
					if(!tfile.exists())tfile.mkdirs();
					String tPath = tpath + fn;
					rtpath+=fn;
					tfile=new File(rtpath);
					final File tempfile=tfile;
					FileUtils.copyFile(new File(opath), tfile);
					new Thread(){
						public void run() {
							try {
								int cnt=0;
								while(tempfile.getParentFile().exists()){
									Thread.sleep(5000);
									tempfile.getParentFile().delete();
									if(cnt>100)return;
									cnt++;
								}
							} catch (Exception e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
					}.start();
					return tpath;
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
    	return null;
    }
    //파일로 존재하지 않을경우 디비에서 가져와서 파일로 저장한다
    public static  ArrayList<String> getBoardAttachmentsFileNames(Long id, HttpServletRequest req, boolean isreset){
    	ArrayList<String> rslt = new ArrayList<String>();
    	//String globalFilePathStr=Moumi.getMessageBundle().getString("moumi.dir.upload")+"/boardattachment";
    	boolean fromFile = false;
    	String globalFilePathStr = getGlobalBoardAttachmentsPath();
    	if(!globalFilePathStr.endsWith("/")){
    		globalFilePathStr+="/";
    	}
    	System.out.println("globalFilePathStr ==========  " + globalFilePathStr );
    	File globalFilePath = new File(globalFilePathStr);

    	if(!globalFilePath.exists()){
    		globalFilePath.mkdirs();
    	}
    	String boardAttachPath = globalFilePathStr + id + "/";
    	System.out.println("boardAttachPath ==========  " + boardAttachPath );
    	File boardAttachFile=new File(boardAttachPath);
    	if(isreset){
    		if(boardAttachFile.exists()){
    			try {
					FileUtils.deleteDirectory(boardAttachFile);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
    		}
    	}
    	File fnsFile = new File(boardAttachPath+"fns");
    	System.out.println("boardAttachFile 1111 ==========  " + boardAttachFile );
    	if(boardAttachFile.exists()){
			try {
				System.out.println("fnsFile 1111 ==== "+ fnsFile);
				if(fnsFile.exists()){
					System.out.println("fnsFile ==== "+ fnsFile);
					FileInputStream fis = new FileInputStream(fnsFile);
					InputStreamReader reader = new InputStreamReader(fis,"utf-8");
					BufferedReader br = new BufferedReader(reader);
					String line = br.readLine();
					while(line != null){
						rslt.add(line);
						line = br.readLine();
					}
					br.close();
					reader.close();
					fis.close();
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			fromFile = true;
    	}else{
    		boardAttachFile.mkdirs();
    		System.out.println("boardAttachFile 222 ==== "+ boardAttachFile);
    		Map<String, List<Byte>> map = getBoardAttachmentsFromDB(id, req);
    		if(map == null)return rslt;
    		Set<String> filenames = map.keySet();
    		String fns = StringUtils.join(filenames.iterator(), "\r\n");
    		try {
    			PrintWriter pw = new PrintWriter(fnsFile,"utf-8");
        		pw.write(fns);
        		pw.flush();
        		pw.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
    		for (String fn : filenames) {
    			rslt.add(fn);
    			try {
    				File fnFile = new File(boardAttachPath+"files/"+fn);
    				fnFile.getParentFile().mkdirs();
    				fnFile.createNewFile();
    				List<Byte> flist = map.get(fn);
    				if(flist == null)continue;
        			FileOutputStream fos = new FileOutputStream(fnFile);
        			for(int b:flist)fos.write(b);
        			fos.flush();
        			fos.close();
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
			}

    	}

    	/*System.out.println("=========================================================="
    	            +id+" - "+(fromFile?"파일에서":"디비에서")+"가져옴 걸린초 : "+sw.getTime());*/
        return rslt;
    }
    public static Map<String, List<Byte>> getBoardAttachmentsFromDB(Long id,HttpServletRequest req){
    	Map<String, List<Byte>> map=null;
    	//req.getSession().getServletContext().setAttribute("onattachdownload", id);
    	CommonDBManager acdbm = new CommonDBManager();
    	ResultSet ars = null;
        try{
        	ars = acdbm.execQuery("select ATTACHMENTS  from MOUMI_BOARD  where id=? ",id);
    		if(ars.next()){
    			InputStream is = ars.getBinaryStream(1);
    			System.out.println("is ==== "+is);
    			if(is != null){
    				ObjectInputStream ois = new ObjectInputStream(is);
    				map = (Map<String, List<Byte>>)ois.readObject();
    				ois.close();
    				is.close();
    			}
    		}

        }catch(Exception ex){
        	ex.printStackTrace();
        }finally{
        	try{ars.close();}catch(Exception e){}
        	acdbm.execClose();
        }
        //req.getSession().getServletContext().setAttribute("onattachdownload", null);
        return map;
    }
}
