/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package kr.co.kihyun.service.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.co.kihyun.beans.entity.TotReport;
import kr.co.kihyun.beans.entity.util.MPersistenceManager;
import kr.co.kihyun.beans.entity.util.PMF;
import kr.co.kihyun.db.CommonDBManager;
import kr.co.kihyun.io.FileUtil;
import kr.co.kihyun.io.IUploadable;
import kr.co.kihyun.lang.MLong;
import kr.co.kihyun.lang.MString;
import kr.co.kihyun.service.DeptService;
import kr.co.kihyun.service.TotReportService;
import kr.co.kihyun.service.vo.CodeVO;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Kts
 */
@WebServlet("/servlet/kr.co.kihyun.service.servlet.AjaxProcessServlet")
public class AjaxProcessServlet extends HttpServlet {
    private static final Logger LOG = LoggerFactory.getLogger(AjaxProcessServlet.class);
    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     * @throws SQLException
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException, SQLException {
        response.setContentType("application/x-json;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            //업무처리구분자
            String procType = MString.checkNull(request.getParameter("proc_type"));

            if( LOG.isDebugEnabled() ) {
                LOG.debug("procType={}", procType);
            }

            if( procType.equals("dept_lov")) {
                //부서에 대한 List of Value(코드와 값)를 구함
                processListOfValueForDept(request, response);
            } else if( procType.equals("attatch_file")) {
                //첨부파일의 리스트를 구한다.
                attachmentsMapByReportID(request, response);
            } else if( procType.equals("board_attatch_file")) {
                //첨부파일의 리스트를 구한다.
                attachmentsMapByBoardID(request, response);
            } else if( procType.equals("send_neis_recog")) {
                //결재진행상태를 확인한다.
                sendNeisRecogByReportID(request, response);
            }

        } finally {
            out.close();
        }
    }

    /**
     * 부서에 대한 List of Value를 Json형태로 변환하여 응답하는 메소드
     * @param request - 요청객체
     * @param response - 응답객체
     * @throws ServletException
     * @throws IOException
     */
    private void processListOfValueForDept(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        String deptId = MString.checkNull(request.getParameter("deptId"));
        int lovType = Integer.parseInt(request.getParameter("lov_type"));
        if( LOG.isDebugEnabled() ) {
            LOG.debug("lovType={}, deptId={}", lovType, deptId);
        }
        DeptService.TYPE type = null;
        if( lovType == DeptService.TYPE.DEPT_OF_SAME_ORGAN.ordinal() ) {
            //기관이 같은 모든 부서 목록
            type = DeptService.TYPE.DEPT_OF_SAME_ORGAN;
        }else if( lovType == DeptService.TYPE.SCHOOL_OF_SAME_ORGAN.ordinal() ) {
            //기관이 같은 학교 목록
            type = DeptService.TYPE.SCHOOL_OF_SAME_ORGAN;
        }else if( lovType == DeptService.TYPE.SAME_ROOT_DEPT.ordinal() ) {
            //Root Dept가 같은 부서 목록
            type = DeptService.TYPE.SAME_ROOT_DEPT;
        }
        PersistenceManager pm = new MPersistenceManager(PMF.get().getPersistenceManager());
        Transaction tx = pm.currentTransaction();
        tx.begin();

        DeptService deptService = new DeptService(pm);
        List deptList = deptService.getLOVFromDept(type, deptId);
        //Json형태로 변환하는 메소드 호출
        String jsonOutput = makeCodeListToJson(deptList);

        //v2. 9.크로스사이트 스크립트 (PrintWrier) : Update by KWON,HAN
//        if( jsonOutput != null ) out.print(jsonOutput);

        if( jsonOutput != null ) {
            // 수정 : 외부 입력값 필터링
            String filtered_jsonOutput = jsonOutput.replaceAll("<","").replaceAll(">","").replaceAll("&","");
            LOG.debug("v2 9.크로스사이트 스크립트 (PrintWrier) : AjaxProcessServlet.processListOfValueForDept() filtered_jsonOutput={}, Not Test", filtered_jsonOutput);
            out.print(filtered_jsonOutput);
        }
        //========================================

        tx.commit();
    }

    /**
     * 결과목록을 Json형태로 변환하는 메소드
     * @param list - 결과목록
     * @return String - Json형태의 문자열
     */
    private String makeCodeListToJson(List list) {
        int size = list.size();
        if( size > 0 ) {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for( int i = 0; i < size; i++ ) {
                CodeVO codeVO = (CodeVO)list.get(i);
                if( i >= 1 ) sb.append(",");
                sb.append("{");
                sb.append("\"value\":\"");
                sb.append(codeVO.getValue());
                sb.append("\",\"code\":\"");
                sb.append(codeVO.getCode());
                sb.append("\"}");
            }
            sb.append("]");
//            if( LOG.isDebugEnabled() ) {
//                LOG.debug("result={}", sb.toString());
//            }
            return sb.toString();
        }
        return null;
    }


   /**
     * 첨부파일명을 Json형태로 변환하여 응답하는 메소드
     * @param request - 요청객체
     * @param response - 응답객체
     * @throws ServletException
     * @throws IOException
     */
    private void attachmentsMapByReportID(HttpServletRequest request, HttpServletResponse response) throws ServletException, SQLException, IOException {

        int index = Integer.parseInt(request.getParameter("index"));
        String fileIndex = MString.checkNull(request.getParameter("file_index"));
        Long reportID = MLong.parseLong(request.getParameter("report_id"));
        PrintWriter out = response.getWriter();
        Map<String, List<Byte>> attachmentsMap;

        CommonDBManager cdb = new CommonDBManager();
        ResultSet rs = null;
        PersistenceManager pm = new MPersistenceManager(PMF.get().getPersistenceManager());
        Transaction tx = pm.currentTransaction();

        try{
        	rs = cdb.execQuery("SELECT ATTACHMENTS_PATH AS FILES_NM, DOC_ID AS DOCID, DEPT_ID AS DEPTID FROM MOUMI_TOT_REPORT WHERE ID = ?", reportID);

            StringBuilder sb = new StringBuilder();
            String fileNameEncode = "";

            if( rs.next()) {
            	sb.delete(0,sb.length());
            	if(null != rs.getObject("FILES_NM")){
            		sb.append("[");
                    String [] files_nm = rs.getString(1).split(";");
                    String docID = rs.getString(2);
                    String deptID = rs.getString(3);
                    for (int i=0; i < files_nm.length; i++) {
                        fileNameEncode = URLEncoder.encode(files_nm[i], "UTF-8");

                        if( i >= 1 ) sb.append(",");
                        sb.append("{");
                        sb.append("\"index\":\"");
                        sb.append(index);
                        sb.append("\",\"fileIndex\":\"");
                        sb.append(fileIndex);
                        sb.append("\",\"reportID\":\"");
                        sb.append(reportID);
                        sb.append("\",\"docID\":\"");
                        sb.append(docID);
                        sb.append("\",\"deptID\":\"");
                        sb.append(deptID);
                        sb.append("\",\"fileName\":\"");
                        sb.append(files_nm[i]);
                        sb.append("\",\"fileNameEncode\":\"");
                        sb.append(fileNameEncode);
                        sb.append("\"}");
                    }
                    sb.append("]");

                }else{

			        tx.begin();

			        IUploadable uploadable = pm.getObjectById(TotReport.class, reportID);
			        attachmentsMap = uploadable.getAttachments();

			        int i = 0;
			        if (attachmentsMap == null || attachmentsMap.isEmpty()) {
			            sb = null;
			        } else {
			            if( sb != null ) {   //v2. 2.널 포인터 역참조 (변수) : Add by KWN.HAN
			                //Json형태로 변환하는 메소드 호출
			                sb.append("[");
			                for (String fileName : attachmentsMap.keySet()) {
			                    fileNameEncode = URLEncoder.encode(fileName, "UTF-8");

			                    if( i >= 1 ) sb.append(",");
			                    sb.append("{");
			                    sb.append("\"index\":\"");
			                    sb.append(index);
			                    sb.append("\",\"fileIndex\":\"");
			                    sb.append(fileIndex);
			                    sb.append("\",\"reportID\":\"");
			                    sb.append(reportID);
			                    sb.append("\",\"fileName\":\"");
			                    sb.append(fileName);
			                    sb.append("\",\"fileNameEncode\":\"");
			                    sb.append(fileNameEncode);
			                    sb.append("\"}");
			                    i=1+1;
			                }
			                sb.append("]");
			            }  //+++++++++++++++++++++++++++++++++++++++++++++
			        }
			        tx.commit();
                }
            	if( sb != null ) out.print(sb);
            	sb = null;
            }


        }catch(Exception e){
        	e.printStackTrace();
        	if(tx.isActive() ) tx.rollback();
        }finally{
        	if(null != rs) rs.close();
        	cdb.execClose();
        	pm.close();
        }

    }

   /**
     * 첨부파일명을 Json형태로 변환하여 응답하는 메소드
     * @param request - 요청객체
     * @param response - 응답객체
     * @throws ServletException
     * @throws IOException
     */
    private void attachmentsMapByBoardID(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        Long boardID = MLong.parseLong(request.getParameter("board_id"));

        ArrayList<String> fns= FileUtil.getBoardAttachmentsFileNames(boardID, request,false);

        if(fns==null||fns.size()==0){
        	out.print("File is Empty");
        	return;
        }
		ArrayList<String > list=new ArrayList<String>();
    	for(String fileName:fns){
               String fileNameEncode = URLEncoder.encode(fileName, "UTF-8");
               StringBuilder sb=new StringBuilder();
               sb.append("{");
               sb.append("\"boardID\":\"");
               sb.append(boardID);
               sb.append("\",\"fileName\":\"");
               sb.append(fileName);
               sb.append("\",\"fileNameEncode\":\"");
               sb.append(fileNameEncode);
               sb.append("\"}");
            list.add(sb.toString());
           }
    	String rslt="["+StringUtils.join(list.toArray(),",")+"]";
    	out.print(rslt);
    }

   /**
     * 제출자료에서 결재대기중(진행), 결재완료된 제출자료의 갯수를 Json형태로 변환하여 응답하는 메소드
     * @param request - 요청객체
     * @param response - 응답객체
     * @throws ServletException
     * @throws IOException
     */
    private void sendNeisRecogByReportID(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();

        Long reportID = MLong.parseLong(request.getParameter("report_id"));

        //if( LOG.isDebugEnabled() ) {
        //    LOG.debug("reportID={}", reportID.toString());
        //}

        PersistenceManager pm = new MPersistenceManager(PMF.get().getPersistenceManager());
        Transaction tx = pm.currentTransaction();
        tx.begin();

        // 결재대기중(진행), 결재완료된 제출자료의 갯수를 조회한다.
        // 1건이라도 있으면 서식을 수정해선 안된다.
        TotReportService totReportService = new TotReportService(pm);
        int unModifiableCount = totReportService.getUnModifiableCountByReportId(reportID);

        //LOG.info("AjaxProcessServlet.sendNeisRecogByReportID() reportID : {}, report count(prss = 5 or 6) : {}", new Object[] {reportID, unModifiableCount});

        StringBuilder sb = new StringBuilder();

        if( sb != null ) {   //v2. 2.널 포인터 역참조 (변수) : Add by KWN.HAN
            //Json형태로 변환하는 메소드 호출
            sb.append("[");
                sb.append("{");
                sb.append("\"reportID\":\"");
                sb.append(reportID);
                sb.append("\",\"unModifiableCount\":\"");
                sb.append(unModifiableCount);
                sb.append("\"}");
            sb.append("]");
        }  //+++++++++++++++++++++++++++++++++++++++++++++

        if( sb != null ) out.print(sb);

        tx.commit();
    }


    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
			processRequest(request, response);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
			processRequest(request, response);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "AjaxProcessServlet";
    }// </editor-fold>

}
