
package nlib.bbs.web;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import nlib.bbs.service.ArticleVO;
import nlib.bbs.service.AttachFileVO;
import nlib.bbs.service.QnaService;
import nlib.cmm.NlibCommonController;
import nlib.cmm.service.CodeService;
import nlib.cmm.service.NlibProperty;
import nlib.cmm.service.PagingVO;
import nlib.user.service.NlibLoginVO;
import nlib.util.StringUtil;

@Controller
public class QnaController extends NlibCommonController {

	private static final Logger log = LoggerFactory.getLogger(QnaController.class);
	
	static final int DEFUALT_PAGE_SIZE = NlibProperty.getInt("list.paging.page.size", 10);
	
	static final String BD_TYPE_QNA = "QNA";
	
	@Resource(name = "qnaService")
	private QnaService qnaService;
	
	@Resource(name="codeService")
	private CodeService codeService;

	
	/**
	 * 목록 화면을 표시한다. 
	 * 
	 * @param req
	 * @return
	 */
	@RequestMapping("/bbs/listQnas.do")
	public String listQnas(
			HttpServletRequest req, 
			@RequestParam Map<String, String> paramMap,
			ArticleVO searchArticleVO,
			ModelMap model
			) throws Exception {

		model.addAttribute("searchArticle", searchArticleVO);
    	
    	return "nlib/bbs/listQnas";
	}

	/**
	 * 목록 조회한다.
	 * 
	 * @param request
	 * @return
	 */
	@RequestMapping(value="/bbs/listQnasAjax.do")
	public ResponseEntity<String> listQnasAjax(
			HttpServletRequest request, 
			Authentication authentication,
			@RequestBody ArticleVO searchArticleVO) throws Exception {

		String message = null;
		boolean needToQeury = true;
		
		if(searchArticleVO.getPageIndex() < 1) searchArticleVO.setPageIndex(1);
		if(searchArticleVO.getPageSize() < 1) searchArticleVO.setPageSize(DEFUALT_PAGE_SIZE);
		searchArticleVO.setMngOrgCd(getCurCouncilCd(request));
		
		String mbInfoId = getMbInfoId(request);
		searchArticleVO.setLoginedMbInfoId(mbInfoId);
		if(StringUtil.equalsIgnoreCase(searchArticleVO.getSearchQuestionType(), "USER")) {
			searchArticleVO.setSearchMbInfoId(mbInfoId);
			if(StringUtil.isEmpty(mbInfoId)) needToQeury = false;
		} else {
			searchArticleVO.setSearchMbInfoId(null);
		}
		
		List<ArticleVO> list = null;
		int totRecordCount = 0;
		
		if(needToQeury) {
			list = qnaService.listArticles(searchArticleVO);
			totRecordCount = qnaService.countArticles(searchArticleVO);
		} else {
			list = new ArrayList<ArticleVO>();
			message = "로그인 후, 이용하여 주시기 바랍니다";
		}
		
		//-------------------------------
		// JSON변환 응답 처리
		//-------------------------------
    	// JS-GRID 페이징 처리를 포함한 응답값 처리
    	// {data: [{...}], 
    	//  itemsCount: 255
    	// }
    	HashMap<String, Object> retMap = new HashMap<String, Object>();
    	retMap.put("data", list);
    	retMap.put("itemsCount", totRecordCount);
    	retMap.put("message", message);
    	
    	PagingVO pageVO = new PagingVO();
	  	pageVO.setPagingVO(totRecordCount, searchArticleVO.getPageIndex(), searchArticleVO.getPageSize());
	  	retMap.put("pagingPageIndex"     , pageVO.getPageIndex());
	  	retMap.put("pagingTotRecordCount", pageVO.getTotRecordCount());
	  	retMap.put("pagingStartPage"     , pageVO.getStartPage());
	  	retMap.put("pagingEndPage"       , pageVO.getEndPage());
	  	retMap.put("pagingLastPage"      , pageVO.getLastPage());
    	
    	return makeResponseEntityJson(retMap);
	}

	/**
	 * 알림 상세 내용 조회한다.
	 * 
	 * @param req
	 * @return
	 */
	@RequestMapping("/bbs/selectQnaArticle.do")
	public String selectQnaArticle(HttpServletRequest request, Authentication authentication, ArticleVO searchArticleVO, ModelMap model) throws Exception {

		// 읽음처리 및 상세내용 조회 
		searchArticleVO.setLoginedMbInfoId(getMbInfoId(request));
		ArticleVO articleVO = null;
		
		String canRead = qnaService.canRead(searchArticleVO);
		if(canRead != null) {
			model.addAttribute("message", canRead);
			articleVO = searchArticleVO;
		} else {
			articleVO = qnaService.selectArticle(searchArticleVO);	
		}
		
		model.addAttribute("searchArticle", searchArticleVO);
		model.addAttribute("article", articleVO);
    	
    	return "nlib/bbs/selectQnaArticle";
	}

	/**
	 * 묻고답하기 글작성화면을 표출한다.
	 * 
	 * @param req
	 * @return
	 */
	@Secured("ROLE_USER")
	@RequestMapping({"/bbs/insertQnaForm.do", "/bbs/updateQnaForm.do"})
	public String insertQnaForm(
			  HttpServletRequest request
			, ArticleVO searchArticleVO
			, RedirectAttributes redirectAttrs
			, ModelMap model) throws Exception {
		
		NlibLoginVO nlibLoginVO = getNlibLoginVO(request);
		
		searchArticleVO.setLoginedMbInfoId(getMbInfoId(request));
		Map rAttrs = redirectAttrs.getFlashAttributes();
		ArticleVO redirectSearchArticleVO = (ArticleVO)rAttrs.get("searchArticle");
		
		if(redirectSearchArticleVO != null && StringUtil.isNotEmpty(redirectSearchArticleVO.getTitle())) {
			searchArticleVO = redirectSearchArticleVO;
		} else {
			ArticleVO articleVO = qnaService.selectArticle(searchArticleVO);
			if(articleVO != null && !StringUtil.isEmpty(articleVO.getTitle())) {
				articleVO.setSearchKeyword(searchArticleVO.getSearchKeyword());
				articleVO.setPageIndex(searchArticleVO.getPageIndex());
				articleVO.setPageSize(searchArticleVO.getPageSize());
				
				searchArticleVO = articleVO;
			}
		}
		
		searchArticleVO.setLoginedMbInfoId(nlibLoginVO.getMbInfoId());
		searchArticleVO.setLoginedName(nlibLoginVO.getName());
		searchArticleVO.setEmail(nlibLoginVO.getEmail());
		
		model.addAttribute("searchArticle", searchArticleVO);

		return "nlib/bbs/insertQnaForm";
	}


	/**
	 * 묻고답하기 등록 처리한다. 
	 * 
	 * @param req
	 * @param authentication
	 * @param paramMap
	 * @param model
	 * @return
	 */
	@Secured("ROLE_USER")
	@RequestMapping("/bbs/insertQnaArticle.do")
	public String insertQna(HttpServletRequest request
			, Authentication authentication
			, ArticleVO articleVO
			, String fileList
			, RedirectAttributes redirectAttrs
			, ModelMap model) throws Exception {
		
		NlibLoginVO loginVO = getNlibLoginVO(authentication);
		
		String message = null;
		if(loginVO == null || StringUtil.isEmpty(loginVO.getMbInfoId())) {
			message = "로그인하신 후, 이용하여 주시기 바랍니다.";
			log.error("inserQna > " + message);
	    	redirectAttrs.addFlashAttribute("searchArticle", articleVO);
	    	redirectAttrs.addFlashAttribute("message", message);
	    	redirectAttrs.addFlashAttribute("title", articleVO.getTitle());
	    	return "redirect:/bbs/insertQnaForm.do";
		}
		
		//---------------------------
		// 기본 정보 설정 
		//---------------------------
		articleVO.setRegId(loginVO.getMbInfoId());
		articleVO.setMngOrgCd(getCurCouncilCd(request)); // 문화원코드
		articleVO.setBdType(BD_TYPE_QNA);
		articleVO.setAnswerYn("N");
		articleVO.setAnswer(null);
		if(StringUtil.isEmpty(articleVO.getEmailRecvYn())) articleVO.setEmailRecvYn("N");
		if(StringUtil.isEmpty(articleVO.getSecretYn())) articleVO.setSecretYn("N");


		//---------------------------
		// 첨부파일 정보 설정 
		//---------------------------
		if(StringUtil.isNotEmpty(fileList)) {
			
	    	String fileListJsonStr = fileList;
	    	if(fileListJsonStr.startsWith("&")) fileListJsonStr = StringEscapeUtils.unescapeHtml(fileListJsonStr);
	    	if(fileListJsonStr.startsWith("\"")) fileListJsonStr = fileListJsonStr.substring(1);
	    	if(fileListJsonStr.endsWith("\"")) fileListJsonStr = fileListJsonStr.substring(0, fileListJsonStr.length()-1);
	    	fileListJsonStr = fileListJsonStr.replaceAll("\\\\", "");
			
	    	log.debug("fileListJsonStr : " + fileListJsonStr);
	    	
	    	ObjectMapper mapper = new ObjectMapper();
	    	List<Map<String, Object>> fileListObj = null;
	    	try {
	    		fileListObj = mapper.readValue(fileListJsonStr, new TypeReference<List<Map<String, Object>>>() {
	            });
	    		
			} catch (JsonMappingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (JsonProcessingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    	
	    	if(fileListObj != null && fileListObj.size() > 0) {
	    		
				String attachFileId = (String)(fileListObj.get(0).get("attachFileId"));
				if(StringUtil.isEmpty(attachFileId)) {
					log.error("첨부파일 아이디(attachFileId) 값은 필수 항목입니다. 첨부파일 처리에 실패하였습니다. 그러나, 게시물 등록은 계속 진행됩니다.");
				}
				
				if(StringUtil.isNotEmpty(attachFileId)) {
					articleVO.setBdAttachFileId(attachFileId);

	    			String fileSStreCours = NlibProperty.getProperty("fileupload.base.path") + NlibProperty.getProperty("fileupload.bbs.qna.subpath") + "/";
		    		List<AttachFileVO> attachFiles = new ArrayList<AttachFileVO>();
		    		
		    		for(int i=0; i<fileListObj.size(); i++) {
		    			Map finfo = fileListObj.get(i);
		    			AttachFileVO fVO = new AttachFileVO();
		    			
		    			fVO.setAttachFileId(attachFileId);
		    			fVO.setFileStrePath(fileSStreCours);
		    			fVO.setStreFileNm((String)finfo.get("streFileNm"));
		    			fVO.setOrignlFileNm((String)finfo.get("orignlFileNm"));
		    			fVO.setFileExt((String)finfo.get("fileExt"));
		    			fVO.setFileSize(((Integer)finfo.get("fileSize")).intValue());
		    			
		    			File f = new File(fVO.getFileStrePath() + fVO.getStreFileNm());
		    			if(!f.exists() || !f.isFile()) continue;
		    			
		    			attachFiles.add(fVO);
		    		}
		    		articleVO.setAttachFiles(attachFiles);
				}

	    	}
	    	
		}
		
		//---------------------------
		// 등록처리 
		//---------------------------
    	ArticleVO ret = qnaService.insertArticle(articleVO);
    	
    	if(ret == null || ret.getResultCode() == null || !ret.getResultCode().startsWith("S")) {
    		// 등록 실패인 경우
    		message = (ret == null ? "처리에 실패하였습니다." : ret.getResultMessage());
    		redirectAttrs.addFlashAttribute("message", message);
    		redirectAttrs.addFlashAttribute("searchArticle", articleVO);
    		return "redirect:/board/insertQnAForm.do";
    	}

    	redirectAttrs.addFlashAttribute("message", "성공적으로 등록되었습니다.");
    	
		return "redirect:/bbs/listQnas.do";
	}

	/**
	 * 게시글을 수정한다. 
	 * 
	 * @param req
	 * @return
	 */
	@Secured("ROLE_USER")
	@RequestMapping("/bbs/updateQnaArticle.do")
	public String updateQnaArticle(
			HttpServletRequest request
		  , ArticleVO articleVO
		  , String fileList
		  , String delFileList
		  , RedirectAttributes redirectAttrs
		  , ModelMap model) throws Exception {
		
		NlibLoginVO nlibLoginVO = getNlibLoginVO(request);
		
		// 권한 및 변경 가능 상태 체크 
		articleVO.setLoginedMbInfoId(getMbInfoId(request));
		String message = qnaService.canModify(articleVO);
		if(message != null) {
			redirectAttrs.addFlashAttribute("searchArticle", articleVO);
	    	redirectAttrs.addFlashAttribute("message", message);
			return "redirect:/bbs/listQnas.do";
		}
		
		articleVO.setModId(nlibLoginVO.getMbInfoId());
		

		//---------------------------
		// 첨부파일 정보 설정 
		//---------------------------
		if(StringUtil.isNotEmpty(fileList)) {
			
	    	String fileListJsonStr = fileList;
	    	if(fileListJsonStr.startsWith("&")) fileListJsonStr = StringEscapeUtils.unescapeHtml(fileListJsonStr);
	    	if(fileListJsonStr.startsWith("\"")) fileListJsonStr = fileListJsonStr.substring(1);
	    	if(fileListJsonStr.endsWith("\"")) fileListJsonStr = fileListJsonStr.substring(0, fileListJsonStr.length()-1);
	    	fileListJsonStr = fileListJsonStr.replaceAll("\\\\", "");
			
	    	log.debug("fileListJsonStr : " + fileListJsonStr);
	    	
	    	ObjectMapper mapper = new ObjectMapper();
	    	List<Map<String, Object>> fileListObj = null;
	    	try {
	    		fileListObj = mapper.readValue(fileListJsonStr, new TypeReference<List<Map<String, Object>>>() {
	            });
	    		
			} catch (JsonMappingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (JsonProcessingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    	
	    	if(fileListObj != null && fileListObj.size() > 0) {
	    		
				String attachFileId = (String)(fileListObj.get(0).get("attachFileId"));
				if(StringUtil.isEmpty(attachFileId)) {
					log.error("첨부파일 아이디(attachFileId) 값은 필수 항목입니다. 첨부파일 처리에 실패하였습니다. 그러나, 게시물 등록은 계속 진행됩니다.");
				}
				
				if(StringUtil.isNotEmpty(attachFileId)) {
					if(StringUtil.isNotEmpty(articleVO.getBdAttachFileId())) articleVO.setBdAttachFileId(attachFileId);

	    			String fileSStreCours = NlibProperty.getProperty("fileupload.base.path") + NlibProperty.getProperty("fileupload.bbs.qna.subpath") + "/";
		    		List<AttachFileVO> attachFiles = new ArrayList<AttachFileVO>();
		    		
		    		for(int i=0; i<fileListObj.size(); i++) {
		    			Map finfo = fileListObj.get(i);
		    			AttachFileVO fVO = new AttachFileVO();
		    			
		    			fVO.setAttachFileId(attachFileId);
		    			fVO.setFileStrePath(fileSStreCours);
		    			fVO.setStreFileNm((String)finfo.get("streFileNm"));
		    			fVO.setOrignlFileNm((String)finfo.get("orignlFileNm"));
		    			fVO.setFileExt((String)finfo.get("fileExt"));
		    			fVO.setFileSize(((Integer)finfo.get("fileSize")).intValue());
		    			
		    			File f = new File(fVO.getFileStrePath() + fVO.getStreFileNm());
		    			if(!f.exists() || !f.isFile()) continue;
		    			
		    			attachFiles.add(fVO);
		    		}
		    		articleVO.setAttachFiles(attachFiles);
				}

	    	}
	    	
		}
		
		// 첨부파일 삭제 
		if(StringUtil.isNotEmpty(delFileList)) {

	    	String removedFileListJsonStr = delFileList;
	    	if(removedFileListJsonStr.startsWith("&")) removedFileListJsonStr = StringEscapeUtils.unescapeHtml(removedFileListJsonStr);
	    	if(removedFileListJsonStr.startsWith("\"")) removedFileListJsonStr = removedFileListJsonStr.substring(1);
	    	if(removedFileListJsonStr.endsWith("\"")) removedFileListJsonStr = removedFileListJsonStr.substring(0, removedFileListJsonStr.length()-1);
	    	removedFileListJsonStr = removedFileListJsonStr.replaceAll("\\\\", "");
			
	    	log.debug("removedFileListJsonStr : " + removedFileListJsonStr);
	    	
	    	ObjectMapper mapper = new ObjectMapper();
	    	List<Map<String, Object>> removedFileListObj = null;
	    	try {
	    		removedFileListObj = mapper.readValue(removedFileListJsonStr, new TypeReference<List<Map<String, Object>>>() {
	            });
	    		
			} catch (JsonMappingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (JsonProcessingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    	
	    	if(removedFileListObj != null && removedFileListObj.size() > 0) {
	    		
				String attachFileId = (String)(removedFileListObj.get(0).get("attachFileId"));
				if(StringUtil.isEmpty(attachFileId)) {
					log.error("첨부파일 아이디(attachFileId) 값은 필수 항목입니다. 첨부파일 삭제에 실패하였습니다. 그러나, 게시물 등록은 계속 진행됩니다.");
				}
				
				if(StringUtil.isNotEmpty(attachFileId) && attachFileId.equals(articleVO.getBdAttachFileId())) {
					//articleVO.setBdAttachFileId(attachFileId);

	    			//String fileSStreCours = NlibProperty.getProperty("fileupload.base.path") + NlibProperty.getProperty("fileupload.bbs.qna.subpath") + "/";
		    		List<AttachFileVO> removedAttachFiles = new ArrayList<AttachFileVO>();
		    		
		    		for(int i=0; i<removedFileListObj.size(); i++) {
		    			Map remFinfo = removedFileListObj.get(i);
		    			AttachFileVO fVO = new AttachFileVO();
		    			String fileSnStr = (String)remFinfo.get("fileSn");
		    			if(StringUtil.isEmpty(fileSnStr)) {
		    				log.error("파일순번 정보가 존재하지 않습니다. : " + (String)remFinfo.get("streFileNm"));
		    				continue;
		    			}
		    			
		    			int fileSn = 0;
		    			try {
		    				fileSn = Integer.parseInt(fileSnStr);
		    			}catch(Exception e) {
		    				log.error("삭제할 파일순번 정보 오류입니다. : " + fileSnStr + " OF " + (String)remFinfo.get("streFileNm"));
		    				continue;
		    			}
		    			
		    			fVO.setAttachFileId(attachFileId);
		    			fVO.setFileSn(fileSn);
		    			
		    			removedAttachFiles.add(fVO);
		    		}
		    		articleVO.setRemovedAttachFiles(removedAttachFiles);
				}
	    	}
		}
		
		// 수정 처리 
		int ret = qnaService.updateArticle(articleVO);
		if(ret < 1) {
			redirectAttrs.addFlashAttribute("searchArticle", articleVO);
	    	redirectAttrs.addFlashAttribute("message", "수정이 처리되지 못했습니다.");
			return "redirect:/bbs/insertQnaForm.do";
		}
		
		model.addAttribute("searchArticle", articleVO);

    	redirectAttrs.addFlashAttribute("message", "성공적으로 수정하였습니다.");
    	
		return "redirect:/bbs/listQnas.do";
	}

	/**
	 * 게시글을 삭제한다. 
	 * 
	 * @param req
	 * @return
	 */
	@Secured("ROLE_USER")
	@RequestMapping("/bbs/deleteQnaArticle.do")
	public String deleteQnaArticle(
			HttpServletRequest request
		  , ArticleVO articleVO 
		  , RedirectAttributes redirectAttrs
		  , ModelMap model) throws Exception {
		
		NlibLoginVO nlibLoginVO = getNlibLoginVO(request);
		
		// 권한 및 변경 가능 상태 체크 
		articleVO.setLoginedMbInfoId(getMbInfoId(request));
		String message = qnaService.canModify(articleVO);
		if(message != null) {
			redirectAttrs.addFlashAttribute("searchArticle", articleVO);
	    	redirectAttrs.addFlashAttribute("message", message);
			return "redirect:/bbs/insertQnaForm.do";
		}
		
		ArticleVO articleOrgVO = qnaService.selectArticle(articleVO);
		articleOrgVO.setModId(nlibLoginVO.getMbInfoId());
		
		// 삭제 처리 
		int ret = qnaService.deleteArticle(articleOrgVO);
		if(ret < 1) {
			redirectAttrs.addFlashAttribute("searchArticle", articleOrgVO);
	    	redirectAttrs.addFlashAttribute("message", "삭제 처리되지 못했습니다.");
			return "redirect:/bbs/insertQnaForm.do";
		}
		
		model.addAttribute("searchArticle", articleOrgVO);

    	redirectAttrs.addFlashAttribute("message", "성공적으로 삭제되었습니다.");
    	
		return "redirect:/bbs/listQnas.do";
	}
	
	
}