
package nlib.bbs.web;

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.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.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 req
	 * @return
	 */
	@RequestMapping(value="/bbs/listQnasAjax.do")
	public ResponseEntity<String> listQnasAjax(
			HttpServletRequest req, 
			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);
		
		String mbInfoId = getMbInfoId(req);
		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);
    	
    	
    	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 = qnaService.selectArticle(searchArticleVO);

		model.addAttribute("searchArticle", searchArticleVO);
		model.addAttribute("article", articleVO);
    	
    	return "nlib/bbs/selectQnaArticle";
	}

	/**
	 * 묻고답하기 글작성화면을 표출한다.
	 * 
	 * @param req
	 * @return
	 */
	@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(redirectSearchArticleVO.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
	 */
	@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.setRegDd(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>>>() {
	            });
	    		
	            for (Map<String, Object> map : fileListObj) {
	                MapUtils.debugPrint(System.out, "map", map);
	            }
	
			} 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) {
	    		List<AttachFileVO> attachFiles = new ArrayList<AttachFileVO>();
	    		String fileId = null;
	    		for(int i=0; i<fileListObj.size(); i++) {
	    			Map finfo = fileListObj.get(i);
	    			AttachFileVO fVO = new AttachFileVO();
	    			
	    			// 게시물에 첨부파일 ID 설정 
	    			if(i == 0) {
	    				fileId = (String)finfo.get("fileId");
	    				if(StringUtil.isEmpty(fileId)) {
	    					log.error("첨부파일의 FILEID 값은 필수 항목입니다. 첨부파일 처리에 실패하였습니다. 그러나, 게시물 등록은 계속 진행됩니다.");
	    					break;
	    				}
	    				articleVO.setBdAttachFileId(fileId);
	    			}

	    			fVO.setFileMask((String)finfo.get("fileMask"));
	    			fVO.setFileId(fileId);
	    			fVO.setFileSeq(((Integer)finfo.get("fileSeq")).intValue());
	    			fVO.setFileName((String)finfo.get("fileName"));
	    			fVO.setFileSize(((Integer)finfo.get("fileSize")).intValue());
	    			fVO.setAtchTypeCd((String)finfo.get("atchTypeCd"));
	    			fVO.setFileExtsn((String)finfo.get("fileExtsn"));
	    			
	    			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
	 */
	@RequestMapping("/bbs/updateQnaArticle.do")
	public String updateQnaArticle(
			HttpServletRequest request
		  , ArticleVO articleVO 
		  , RedirectAttributes redirectAttrs
		  , ModelMap model) throws Exception {
		
		NlibLoginVO nlibLoginVO = getNlibLoginVO(request);
		
		// 권한 및 변경 가능 상태 체크 
		articleVO.setLoginedMbInfoId(getMbInfoId(request));
		String message = canModify(articleVO);
		if(message != null) {
			redirectAttrs.addFlashAttribute("searchArticle", articleVO);
	    	redirectAttrs.addFlashAttribute("message", message);
			return "redirect:/bbs/insertQnaForm.do";
		}
		
		// 수정 처리 
		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
	 */
	@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 = canModify(articleVO);
		if(message != null) {
			redirectAttrs.addFlashAttribute("searchArticle", articleVO);
	    	redirectAttrs.addFlashAttribute("message", message);
			return "redirect:/bbs/insertQnaForm.do";
		}
		
		// 삭제 처리 
		int ret = qnaService.deleteArticle(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";
	}
	
	public String canModify(ArticleVO articleVO) throws Exception {
		
		if(StringUtil.isEmpty(articleVO.getLoginedMbInfoId())) {
			return "로그인 후, 이용하실 수 있습니다.";
		}
		
		ArticleVO savedArticleVO = qnaService.selectArticle(articleVO);
		
		if("Y".equals(articleVO.getMyQnaYn())) {
			return "본인의 글만 변경할 수 있습니다.";
		}
		
		if("Y".equals(savedArticleVO.getAnswerYn())) {
			return "이미 답변완료된 글은 변경할 수 없습니다.";
		}
		
		return null;
	}
	
}