package kcg.imis.board.web;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import kcg.imis.board.service.BoardService;
import kcg.imis.board.vo.BoardSearchVO;
import kcg.imis.board.vo.BoardVO;
import kcg.imis.board.vo.SearchVO;
import kcg.imis.cmmn.file.FileResponser;
import kcg.imis.sec.LoginUserVO;
import kcg.imis.sec.UserUtil;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springmodules.validation.commons.DefaultBeanValidator;

import egovframework.rte.fdl.property.EgovPropertyService;
import egovframework.rte.fdl.security.userdetails.util.EgovUserDetailsHelper;
import egovframework.rte.ptl.mvc.tags.ui.pagination.PaginationInfo;

/**
 * 
  * @FileName : BoardController.java
  * @Project : 국제해양프로젝트
  * @Date : 2018. 3. 21. 
  * @작성자 : Moon
  * @변경이력 : 
  * @프로그램 설명 : 게시판 컨트롤러
 */
@Controller
@SessionAttributes(types = BoardVO.class)
@RequestMapping("/bbs")
public class BoardController {

	/**
	 * EgovPropertyService - properties값을 가져오는 인터페이스.
	 **/
	@Resource(name = "propertiesService")
	private EgovPropertyService propertiesService;
	
	/**
	 * Validator - 유효성 검사.
	 **/
	@Resource(name = "beanValidator")
	private DefaultBeanValidator beanValidator;
	
	/** 
	 * BoardService - 게시판 데이터처리에 관한 인터페이스.
	 **/
	@Resource(name = "boardService")
	private BoardService boardService;
	
	/**
	 * 게시판 목록 화면을 반환한다.
	 *
	 * @param req Request 객체
	 * @param searchVO 검색, 페이지 정보 객체
	 * @param model 모델 객체
	 * @return 게시판 목록 화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/list.do")
	public String boardList(final HttpServletRequest req, @ModelAttribute("searchVO") final BoardSearchVO searchVO, final Model model) throws Exception {
		
		try {
			
			LoginUserVO user = UserUtil.getMemberInfo();
			
			
			searchVO.setPla1(user.getPlace1());
			searchVO.setPla2(user.getPlace2());
			searchVO.setUserid(user.getUserid());
			// 20180528 검색기능 중에 내용 관련 부분 추가
			searchVO.setBdContent(user.getBdcontent());
			
			/* 페이징 처리 정보 */
			searchVO.setPageUnit(propertiesService.getInt("pageUnit"));
			searchVO.setPageSize(propertiesService.getInt("pageSize"));
			
			/* 페이징 처리 */
			PaginationInfo paginationInfo = new PaginationInfo();
			paginationInfo.setCurrentPageNo(searchVO.getPageIndex());
			paginationInfo.setRecordCountPerPage(searchVO.getPageUnit());
			paginationInfo.setPageSize(searchVO.getPageSize());

			searchVO.setFirstIndex(paginationInfo.getFirstRecordIndex());
			searchVO.setLastIndex(paginationInfo.getLastRecordIndex());
			searchVO.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());
			
			int totSearchCnt = boardService.selectListCnt(searchVO);
			paginationInfo.setTotalRecordCount(totSearchCnt);
			model.addAttribute("paginationInfo", paginationInfo);
			
			/* 게시판 리스트 */
			List<BoardVO> boardList = boardService.selectList(searchVO);
			model.addAttribute("resultList", boardList);

			/* 게시판 상단 페이지 및 게시물 정보 표현을 위한 데이터 */
			int totCnt = boardService.selectTotalCnt(searchVO);
			model.addAttribute("totalCnt", totCnt);

			
		} catch (Exception e) {
			e.printStackTrace();
			return "error/bizError";
		}
		
		if("confer".equals(searchVO.getBbsId())){
			return "board/conferList.tiles";
		}
		
		return "board/boardList.tiles";
		
	}
	
	/**
	 * 게시물의 내용을 확인하는 페이지를 반환한다.
	 * 
	 * @param boardVO 게시판 VO
	 * @param model 모델 객체
	 * @return 게시물 조회 화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/view.do", method = RequestMethod.GET)
	public String boardView(final BoardVO boardVO, final Model model) throws Exception {
		
		try {
			/* 작성자와 조회자가 다른 경우 조회수 증가 */
			BoardVO board = boardService.select(boardVO);
			
			/* 게시판 내용 */
			model.addAttribute("boardVO", board);		
			
			/* 세션 사용자 정보 */
			model.addAttribute("loginUserVO", UserUtil.getMemberInfo());
		} catch (Exception e) {
			e.printStackTrace();
			return "error/bizError";
		}
		
		if ("joint".equals(boardVO.getBbsId())) 
			return "board/jointView.tiles";
		
		if ("confer".equals(boardVO.getBbsId())) 
			return "board/conferView.tiles";

		return "board/boardView.tiles";
	}

	/**
	 * 게시물 추가 화면을 반환한다.
	 * searchVO
	 * @param model 모델 객체
	 * @param boardVO 게시판 VO 
	 * @return 게시물 조회 화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/addView.do", method = RequestMethod.GET)
	public String boardAddView(final Model model, @RequestParam("bbsId") String param) throws Exception {
		
		BoardVO modelAttr = new BoardVO();
		modelAttr.setBbsId(param);
		
		/* 게시물 입력 Form ModelAttribute */
		model.addAttribute("boardVO", modelAttr);
		/* create or modify 플래그 */
		model.addAttribute("registerFlag", "create");
		
		if ("joint".equals(param)) 
			return "board/jointAdd.tiles";
		if ("confer".equals(param)) 
			return "board/conferAdd.tiles";

		return "board/boardAdd.tiles";
		
	}
	
	/**
	 * 게시물을 추가한 후 추가한 게시물 화면으로 이동한다.
	 * 
	 * @param multiRequest multpart타입의 요청 객체
	 * @param boardVO 게시물 정보 객체
	 * @param bindingResult 바인딩 객체
	 * @param model 모델 객체
	 * @param status 세선 상태 객체
	 * @return 게시물  화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/add.do", method = RequestMethod.POST)
	public String boardAdd(final MultipartHttpServletRequest multiRequest, @ModelAttribute("boardVO") final BoardVO boardVO, 
			final BindingResult bindingResult, final Model model, final SessionStatus status) throws Exception {
		
		HashMap<String, Object> map = new HashMap<String, Object>();
		
		/* 인증된 사용자인지 확인 */
		Boolean isAuthenticated = EgovUserDetailsHelper.isAuthenticated();
		if (isAuthenticated) {
			try {
				
				if (bindingResult.hasErrors()) {
					model.addAttribute("boardVO", boardVO);
					return "board/boardAdd.tiles";
				}

				final Map<String, MultipartFile> fileMap = multiRequest.getFileMap();
				
				/* 사용자 정보 입력 */
				LoginUserVO user = UserUtil.getMemberInfo();
				boardVO.setUsrIdx(user.getUserid());
				boardVO.setGrpIdx(user.getPlace1());
				boardVO.setBdIpaddr(multiRequest.getRemoteAddr());
				boardVO.setUsrName(user.getName());
				boardVO.setGrpName(user.getPlace1Str() + " " + user.getPlace2Str());
				
				if("1".equals(boardVO.getBdViewAuth())){
					if(boardVO.getCheckAuth() != null  && boardVO.getCheckAuth().length > 0){
						StringBuffer sb = new StringBuffer();
						for(String str : boardVO.getCheckAuth()){
							sb.append(str);
							if(str.equals(boardVO.getCheckAuth()[boardVO.getCheckAuth().length -1])) continue;
							sb.append(";");	
						}
						boardVO.setBdViewGrp(sb.toString());
					}
				}
				
				map = boardService.insert(boardVO, fileMap);
				
				status.setComplete();

				int bdIdx = (Integer) map.get("bdIdx");
				if ( bdIdx > 0) {
					return "redirect:/bbs/list.do?bbsId=" + boardVO.getBbsId();
				}
			} catch (Exception e) {
				e.printStackTrace();
				return "error/bizError";
			}
		}
		
		return "error/bizError";
	}

	/**
	 * 게시물을 추가한 후 추가한 게시물 화면으로 이동한다.
	 * 
	 * @param boardVO 게시판VO 객체
	 * @param model 모델 객체
	 * @return 게시물  화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/updateView.do", method = RequestMethod.POST)
	public String updateView(final BoardVO boardVO, final Model model) throws Exception {

		BoardVO updateBoard = boardService.select(boardVO);
		try {
			/* 글 작성자와 세션 사용자의 아이디를 비교하여 본인여부를 판단한다 */
			if (updateBoard == null || !UserUtil.isEqualMember(updateBoard.getUsrIdx()) && !UserUtil.isAdmin()) {
				return "redirect:/bbs/view.do?bdIdx=" + boardVO.getBdIdx() + "&bbsId=" + boardVO.getBbsId();
			}
			
			model.addAttribute("boardVO", updateBoard);
			model.addAttribute("registerFlag", "modify");
		} catch (Exception e) {
			e.printStackTrace();
			return "error/bizError";
		}
		
		if ("joint".equals(boardVO.getBbsId())) 
			return "board/jointAdd.tiles";
		else 
			return "board/boardAdd.tiles";
		
	}
	
	/**
	 * 게시물을 수정한다.
	 * 
	 * @param multiRequest multpart타입의 요청 객체
	 * @param boardVO 게시물 정보 객체
	 * @param bindingResult 바인딩 객체
	 * @param model 모델 객체
	 * @param status 세선 상태 객체
	 * @return 게시물  화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/update.do", method = RequestMethod.POST)
	public String update(final MultipartHttpServletRequest multiRequest, @ModelAttribute("boardVO") final BoardVO boardVO, 
			final BindingResult bindingResult, final Model model, final SessionStatus status) throws Exception {
		
		try {
			/* 글 작성자와 세션 사용자의 아이디를 비교하여 본인여부를 판단한다 */
			if (!UserUtil.isEqualMember(boardVO.getUsrIdx()) && !UserUtil.isSysAdmin()) {
				return "redirect:/bbs/view.do?bdIdx=" + boardVO.getBdIdx() + "&bbsId=" + boardVO.getBbsId();
			}
			
			if (bindingResult.hasErrors()) {
				model.addAttribute("boardVO", boardVO);
				model.addAttribute("registerFlag", "modify");
				return "board/boardAdd.tiles";
			}
			
			HashMap<String, Object> map = new HashMap<String, Object>();
			
			String[] deleteDocFiles = multiRequest.getParameterValues("deleteDocFile");
			final Map<String, MultipartFile> fileMap = multiRequest.getFileMap();
			map = boardService.update(boardVO, fileMap, deleteDocFiles);

			status.setComplete();
			
			int bdIdx = (Integer) map.get("bdIdx");
			if ( bdIdx > 0) {
				return "redirect:/bbs/list.do?bbsId=" + boardVO.getBbsId();
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			return "error/bizError";
		}
		
		return "redirect:/bbs/list.do?id=" + boardVO.getBbsId();
	}

	/**
	 * 게시물을 삭제한다.
	 * 
	 * @param boardVO 게시판 VO
	 * @param model 모델 객체
	 * @param status 세선 상태 객체
	 * @return 게시물  화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/delete.do", method = RequestMethod.POST)
	public String delete(final BoardVO boardVO, final Model model, final SessionStatus status) throws Exception {

		try {
			if (!UserUtil.isEqualMember(boardVO.getUsrIdx()) && !UserUtil.isSysAdmin()) {
				return "redirect:/bbs/view.do?bdIdx=" + boardVO.getBdIdx() + "&bbsId=" + boardVO.getBbsId();
			}
			
			HashMap<String, Object> map = new HashMap<String, Object>();
			
			map = boardService.delete(boardVO);
			
			status.setComplete();
			
			if ((Integer) map.get("result") > 0) {
				return "redirect:/bbs/list.do?bbsId=" + boardVO.getBbsId();
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			return "error/bizError";
		}
		
		return "redirect:/bbs/view.do?bdIdx=" + boardVO.getBdIdx() + "&bbsId=" + boardVO.getBbsId();
	}
	
	/**
	 * 게시물을 삭제한다.
	 *
	 * @param bdId 삭제할 게시판 ID
	 * @param deleteBoard 모델 객체
	 * @param status 세선 상태 객체
	 * @return 게시물  화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/selectedDelete.do", method = RequestMethod.POST)
	public String deleteSelected(@RequestParam("id") final String bdId, final int[] deleteBoard, final SessionStatus status) throws Exception {
		/* 관리자만 가능 */
		if (UserUtil.isAdmin()) {
			try {
				/*BoardVO boardVO = BoardVOHandler.getBoardVO(bdId, 0);
				if (deleteBoard != null) {
					boardService.selectAndDelete(boardVO, deleteBoard);
				}*/
			} catch (Exception e) {
				e.printStackTrace();
			}
			status.setComplete();
		}
		return "redirect:/bbs/list.do?id=" + bdId;
	}
	
	/**
	 * 답글쓰기 화면을 반환한다.
	 * 
	 * @param boardVO 게시판 VO
	 * @param model 모델 객체
	 * @param status SessionStatus
	 * @return 답글쓰기 화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/replyView.do", method = RequestMethod.POST)
	public String replyView(BoardVO boardVO, final Model model, final SessionStatus status) throws Exception {
		BoardVO replyVO = new BoardVO();
		replyVO.setBdIdx(boardVO.getBdIdx());
		replyVO.setBdIdxGrp(boardVO.getBdIdx());
		replyVO.setBbsId(boardVO.getBbsId());
		model.addAttribute("boardVO", replyVO);
		model.addAttribute("registerFlag", "reply");
		return "board/boardAdd.tiles";
	}
	
	/**
	 * 답글을 등록하고 조회 화면을 반환한다.
	 * 
	 * @param boardVO 게시물 VO
	 * @param bindingResult BindingResult 
	 * @param model 모델 객체
	 * @param status SessionStatus
	 * @param multiRequest MultipartHttpServletRequest
	 * @return 조회 화면
	 */
	@RequestMapping(value = "/reply.do", method = RequestMethod.POST)
	public String replyAdd(@ModelAttribute("boardVO") final BoardVO boardVO, 
			final BindingResult bindingResult, final Model model, final SessionStatus status, final MultipartHttpServletRequest multiRequest) {

		Boolean isAuthenticated = EgovUserDetailsHelper.isAuthenticated();
		if (isAuthenticated) {
			try {
				if (bindingResult.hasErrors()) {
					model.addAttribute("boardVO", boardVO);
					return "board/boardAdd.tiles";
				}
				
				HashMap<String, Object> map = new HashMap<String, Object>();
				
				final Map<String, MultipartFile> fileMap = multiRequest.getFileMap();
				
				/* 사용자 정보 입력 */
				LoginUserVO user = UserUtil.getMemberInfo();
				boardVO.setUsrIdx(user.getUserid());
				boardVO.setGrpIdx(user.getPlace1());
				boardVO.setBdIpaddr(multiRequest.getRemoteAddr());
				boardVO.setUsrName(user.getName());
				boardVO.setGrpName(user.getPlace1Str() + " " + user.getPlace2Str());
				
				map = boardService.insert(boardVO, fileMap);
				
				status.setComplete();

				int bdIdx = (Integer) map.get("bdIdx");
				if ( bdIdx > 0) {
					return "redirect:/bbs/list.do?bbsId=" + boardVO.getBbsId();
				}
			} catch (Exception e) {
				e.printStackTrace();
				return "error/bizError";
			}
			
		}
		
		return "redirect:/bbs/list.do?id=" + boardVO.getBbsId();
	}
	
	
	/**
	 * 첨부파일로 등록된 파일에 대하여 다운로드를 제공한다.
	 * 
	 * @param boardFileVO 게시판 파일 VO
	 * @param request Request 객체
	 * @param response Response 객체
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/download.do")
	public void cvplFileDownload(@RequestParam("bdIdx") Integer bdIdx, @RequestParam("fileIdx") Integer fileIdx, final HttpServletRequest request, final HttpServletResponse response) throws Exception {
		
		
		BoardVO paramVO = new BoardVO();
		paramVO.setBdIdx(bdIdx);
		BoardVO boardVO = boardService.select(paramVO);
		String orgfileName = boardVO.getOrgFileNames().get(fileIdx);
		String saveFileName = boardVO.getSaveFileNames().get(fileIdx);
		
		String fileFullPath = propertiesService.getString("Globals.fileStorePath") + File.separator + "document" + File.separator + saveFileName ;
		
		
		File file = new File(fileFullPath);
		
		
		if (file.exists()) {
			FileResponser.setResponse(file, orgfileName, request, response);
			BufferedInputStream in = null;
			try {
				in = new BufferedInputStream(new FileInputStream(file));
				FileCopyUtils.copy(in, response.getOutputStream());
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (in != null) {
					try {
						in.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
	
	@RequestMapping(value = "/search.do")
	public String search(final SearchVO searchVO, final Model model, final SessionStatus status) throws Exception {
		

		LoginUserVO user = UserUtil.getMemberInfo();
		
		searchVO.setPla1(user.getPlace1());
		searchVO.setPla2(user.getPlace2());
		searchVO.setUserid(user.getUserid());
		
		model.addAttribute("searchKeyWord", searchVO.getSearchKeyWord());
		model.addAttribute("data", boardService.searchBoard(searchVO));
		
		return "board/searchResult.tiles";
	}
	
}
