package kcg.faics.stats.web;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
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.faics.board.service.BoardService;
import kcg.faics.board.util.BoardUtils;
import kcg.faics.board.util.BoardVOHandler;
import kcg.faics.board.vo.BoardCommentVO;
import kcg.faics.board.vo.BoardFileVO;
import kcg.faics.board.vo.BoardSearchVO;
import kcg.faics.board.vo.BoardVO;
import kcg.faics.cmmn.bbs.BaseCommentService;
import kcg.faics.cmmn.bbs.BaseFileService;
import kcg.faics.cmmn.file.FileResponser;
import kcg.faics.cmmn.service.CodeService;
import kcg.faics.sec.LoginUserVO;
import kcg.faics.sec.UserUtil;

import org.apache.commons.lang.StringUtils;
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.ResponseBody;
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;


/**
 * 외사통계 컨트롤러
 * 
 * @author 하영지
 *
 */
@Controller
@RequestMapping("/stats")
public class StatsController {

	/**
	 * EgovPropertyService - properties값을 가져오는 인터페이스.
	 **/
	@Resource(name = "propertiesService")
	private EgovPropertyService propertiesService;
	
	/**
	 * Validator - 유효성 검사.
	 **/
	@Resource(name = "beanValidator")
	private DefaultBeanValidator beanValidator;
	
	/** 
	 * BoardService - 게시판 데이터처리에 관한 인터페이스.
	 **/
	@Resource(name = "boardService")
	private BoardService boardService;
	
	/** 
	 * BoardFileService - 게시판 파일에 관한 인터페이스.
	 **/
	@Resource(name = "boardFileService")
	private BaseFileService<BoardFileVO> boardFileService;
	
	/** 
	 * BoardCommentService - 게시판 덧글에 관한 인터페이스.
	 **/
	@Resource(name = "boardCommentService")
	private BaseCommentService<BoardCommentVO> boardCommentService;
	
	/** 
	 * CodeService - 코드에 관한 인터페이스.
	 **/
	@Resource(name = "codeService")
	private CodeService codeService;

	/**
	 * 게시판id
	 */
	private final String BOARDID = "stat_bbs";
	
	/**
	 * 게시판 목록 화면을 반환한다.
	 *
	 * @param req Request 객체
	 * @param searchVO 검색, 페이지 정보 객체
	 * @param model 모델 객체
	 * @return 게시판 목록 화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/list.do")
	public String statsList(final HttpServletRequest req, @ModelAttribute("searchVO") final BoardSearchVO searchVO, final Model model) throws Exception {
		
		try {
			// 통계 종류
			model.addAttribute("category", codeService.getCodeValues("STAT", null));
			
			// 게시판 아이디
			searchVO.setId(BOARDID);
			
			/* 페이징 처리 정보 */
			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";
		}
		
		return "stats/statsList.tiles";
	}
	
	/**
	 * 게시물의 내용을 확인하는 페이지를 반환한다.
	 * 
	 * @param boardVO 게시판 VO
	 * @param model 모델 객체
	 * @return 게시물 조회 화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/view.do", method = RequestMethod.GET)
	public String statsView(final BoardVO boardVO, final Model model) throws Exception {
		
		try {

			// 게시판 아이디
			boardVO.setId(BOARDID);
			model.addAttribute("beforeCategory", boardVO.getCategory());
			
			/* 작성자와 조회자가 다른 경우 조회수 증가 */
			BoardVO board = boardService.select(boardVO);
			if (!UserUtil.isEqualMember(board.getUserId())) {
				boardService.incHit(board);	
			}
			/* 게시판 내용 */
			model.addAttribute("boardVO", boardService.select(boardVO));		
			/* 게시판 파일내용 */
			model.addAttribute("boardFileVO", boardFileService.selectList(BoardVOHandler.getBFileVO(boardVO)));
			/* 게시판 덧글내용 */
			model.addAttribute("boardCommentVOList", boardCommentService.selectList(BoardVOHandler.getBCommentVO(boardVO)));
			
			/* 덧글 ModelAttribute */
			model.addAttribute("boardCommentVO", BoardVOHandler.getBCommentVO(boardVO));
			
			/* 세션 사용자 정보 */
			model.addAttribute("loginUserVO", UserUtil.getMemberInfo());
		} catch (Exception e) {
			e.printStackTrace();
			return "error/bizError";
		}
		
		return "stats/statsView.tiles";
	}

	/**
	 * 게시물 추가 화면을 반환한다.
	 * 
	 * @param model 모델 객체
	 * @param boardVO 게시판 VO 
	 * @return 게시물 조회 화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/addView.do", method = RequestMethod.GET)
	public String statsAddView(final Model model, final BoardVO boardVO) throws Exception {

		boardVO.setId(BOARDID);
		model.addAttribute("beforeCategory", boardVO.getCategory());
		
		BoardVO modelAttr = new BoardVO();
		modelAttr.setId(boardVO.getId());

		// 통계 종류
		model.addAttribute("category", codeService.getCodeValues("STAT", null));
		
		/* 게시물 입력 Form ModelAttribute */
		model.addAttribute("boardVO", modelAttr);
		/* create or modify 플래그 */
		model.addAttribute("registerFlag", "create");
		
		return "stats/statsAdd.tiles";
	}
	
	/**
	 * 게시물을 추가한 후 추가한 게시물 화면으로 이동한다.
	 * 
	 * @param multiRequest multpart타입의 요청 객체
	 * @param boardVO 게시물 정보 객체
	 * @param bindingResult 바인딩 객체
	 * @param model 모델 객체
	 * @param status 세선 상태 객체
	 * @return 게시물  화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/add.do", method = RequestMethod.POST)
	public String statsAdd(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>();

		boardVO.setId(BOARDID);
		
		/* 인증된 사용자인지 확인 */
		Boolean isAuthenticated = EgovUserDetailsHelper.isAuthenticated();
		if (isAuthenticated) {
			try {
				/* 유효성 검사 */
				if (bindingResult.hasErrors()) {
					model.addAttribute("boardVO", boardVO);
					model.addAttribute("category", codeService.getCodeValues("STAT", null));
					return "stats/statsAdd.tiles";
				}

				final Map<String, MultipartFile> fileMap = multiRequest.getFileMap();
				
				/* 사용자 정보 입력 */
				LoginUserVO user = UserUtil.getMemberInfo();
				boardVO.setUserId(user.getUserid());
				boardVO.setUserName(user.getName());
				boardVO.setPosition(user.getPosition());
				boardVO.setPlace1(user.getPlace1());
				boardVO.setData1(user.getPlace1Yak());
				boardVO.setData2(user.getPositionStr());
				boardVO.setIsReply(-1);
				map = boardService.insert(boardVO, fileMap);
				
				status.setComplete();

				int result = (Integer) map.get("result");
				int seq = (Integer) map.get("seq");
				if (result > 0 && seq > 0) {
					return "redirect:/stats/view.do?seq=" + seq + "&id=" + boardVO.getId();
				}
			} 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.setId(BOARDID);
		
		BoardVO updateBoard = boardService.select(boardVO);
		try {
			/* 글 작성자와 세션 사용자의 아이디를 비교하여 본인여부를 판단한다 */
			if (updateBoard == null || !UserUtil.isEqualMember(updateBoard.getUserId())) {
				return "redirect:/stats/statsView.do?seq=" + boardVO.getSeq() + "&id=" + boardVO.getId();
			}

			// 통계 종류
			model.addAttribute("category", codeService.getCodeValues("STAT", null));
			
			model.addAttribute("boardVO", updateBoard);
			model.addAttribute("registerFlag", "modify");
			model.addAttribute("boardFileVO", boardFileService.selectList(BoardVOHandler.getBFileVO(updateBoard)));
		} catch (Exception e) {
			e.printStackTrace();
			return "error/bizError";
		}
		
		return "stats/statsAdd.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 {

		boardVO.setId(BOARDID);
		
		try {
			/* 글 작성자와 세션 사용자의 아이디를 비교하여 본인여부를 판단한다 */
			if (!UserUtil.isEqualMember(boardVO.getUserId())) {
				return "redirect:/stats/view.do?seq=" + boardVO.getSeq() + "&id=" + boardVO.getId();
			}
			
			/* 유효성 검사 */
//			beanValidator.validate(boardVO, bindingResult);
			if (bindingResult.hasErrors()) {
				model.addAttribute("boardVO", boardVO);
				model.addAttribute("registerFlag", "modify");
				model.addAttribute("category", codeService.getCodeValues("STAT", null));
				return "stats/statsAdd.tiles";
			}
			
			HashMap<String, Object> map = new HashMap<String, Object>();
			
			String[] deleteFiles = multiRequest.getParameterValues("deleteFile");
			final Map<String, MultipartFile> fileMap = multiRequest.getFileMap();
			map = boardService.update(boardVO, fileMap, deleteFiles);

			status.setComplete();
			
			int result = (Integer) map.get("result");
			int seq = (Integer) map.get("seq");
			
			if (result > 0 && seq > 0) {
				return "redirect:/stats/view.do?seq=" + seq + "&id=" + boardVO.getId();
			}
		} catch (Exception e) {
			e.printStackTrace();
			return "error/bizError";
		}
		
		return "redirect:/stats/list.do?id=" + boardVO.getId();
	}

	/**
	 * 게시물을 삭제한다.
	 * 
	 * @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 {

		boardVO.setId(BOARDID);
		
		try {
			BoardVO deleteBoard = boardService.select(boardVO);
			
			if (deleteBoard == null || !UserUtil.isEqualMember(deleteBoard.getUserId())) {
				return "redirect:/stats/view.do?seq=" + boardVO.getSeq() + "&id=" + boardVO.getId();
			}
			
			HashMap<String, Object> map = new HashMap<String, Object>();
			
			map = boardService.delete(boardVO);
			
			status.setComplete();
			
			if ((Integer) map.get("result") > 0) {
				return "redirect:/stats/list.do?id=" + boardVO.getId();
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			return "error/bizError";
		}
		
		return "redirect:/stats/view.do?seq=" + boardVO.getSeq() + "&id=" + boardVO.getId();
	}
	
	/**
	 * 게시물을 삭제한다.
	 *
	 * @param bdId 삭제할 게시판 ID
	 * @param deleteBoard 모델 객체
	 * @param status 세선 상태 객체
	 * @return 게시물  화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/selectedDelete.do", method = RequestMethod.POST)
	public String deleteSelected(final int[] deleteBoard, final SessionStatus status) throws Exception {
		
		/* 관리자만 가능 */
		if (UserUtil.isAdmin()) {
			try {
				BoardVO boardVO = BoardVOHandler.getBoardVO(BOARDID, 0);
				if (deleteBoard != null) {
					boardService.selectAndDelete(boardVO, deleteBoard);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			status.setComplete();
		}
		return "redirect:/stats/list.do?id=" + BOARDID;
	}
	
	/**
	 * 답글쓰기 화면을 반환한다.
	 * 
	 * @param boardVO 게시판 VO
	 * @param model 모델 객체
	 * @param status SessionStatus
	 * @return 답글쓰기 화면
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/replyView.do", method = RequestMethod.POST)
	public String replyView(final BoardVO boardVO, final Model model, final SessionStatus status) throws Exception {
		boardVO.setId(BOARDID);
		
		// 통계 종류
		model.addAttribute("category", codeService.getCodeValues("STAT", null));
		
		BoardVO replyVO = BoardVOHandler.getBoardVO(boardVO);
		replyVO.setStep(boardVO.getStep());
		replyVO.setGroupSeq(boardVO.getGroupSeq());
		replyVO.setDepth(boardVO.getDepth());
		model.addAttribute("boardVO", replyVO);
		model.addAttribute("registerFlag", "reply");
		return "stats/statsAdd.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) {
		boardVO.setId(BOARDID);
		
		Boolean isAuthenticated = EgovUserDetailsHelper.isAuthenticated();
		if (isAuthenticated) {
			try {
//				beanValidator.validate(boardVO, bindingResult);
				if (bindingResult.hasErrors()) {
					model.addAttribute("boardVO", boardVO);
					return "stats/statsAdd.tiles";
				}
				
				HashMap<String, Object> map = new HashMap<String, Object>();
				
				final Map<String, MultipartFile> fileMap = multiRequest.getFileMap();
				
				/* 사용자 정보 입력 */
				LoginUserVO user = UserUtil.getMemberInfo();
				boardVO.setUserId(user.getUserid());
				boardVO.setUserName(user.getName());
				boardVO.setPosition(user.getPosition());
				boardVO.setPlace1(user.getPlace1());
				boardVO.setData1(user.getPlace1Yak());
				boardVO.setData2(user.getPositionStr());				
				boardVO.setIsReply(1);
				map = boardService.insert(boardVO, fileMap);
				
				status.setComplete();

				int result = (Integer) map.get("result");
				int seq = (Integer) map.get("seq");
				if (result > 0 && seq > 0) {
					return "redirect:/stats/view.do?seq=" + seq + "&id=" + boardVO.getId();
				}
			} catch (Exception e) {
				e.printStackTrace();
				return "error/bizError";
			}
			
		}
		
		return "redirect:/stats/list.do?id=" + boardVO.getId();
	}
	
	/**
	 * 덧글을 등록한다.
	 * 
	 * @param boardCommentVO 덧글 데이터
	 * @param status SessionStatus
	 * @return json 객체
	 */
	@ResponseBody
	@RequestMapping(value = "/commentAdd.json", method = RequestMethod.POST)
	public Object comment(@ModelAttribute("boardCommentVO") final BoardCommentVO boardCommentVO, final SessionStatus status) {
		
		HashMap<String, Object> ret = new HashMap<String, Object>();
		boardCommentVO.setId(BOARDID);
		
		Boolean isAuthenticated = EgovUserDetailsHelper.isAuthenticated();
		if (isAuthenticated) {
			try {
				LoginUserVO user = UserUtil.getMemberInfo();
				boardCommentVO.setUserId(user.getUserid());
				boardCommentVO.setUserName(user.getName());
				
				
				ret = boardCommentService.insert(boardCommentVO);
				if ((Integer) ret.get("result") > 0) {
					ret.put("comment", boardCommentService.select(boardCommentVO));
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		status.setComplete();
		
		return ret;
	}
	
	/**
	 * 댓글을 삭제한다.
	 * 
	 * @param boardCommentVO 댓글 VO
	 * @param status SessionStatus
	 * @return json 객체
	 */
	@ResponseBody
	@RequestMapping("/commentDelete.json")
	public Object commentDelete(final BoardCommentVO boardCommentVO, final SessionStatus status) {
		
		HashMap<String, Object> ret = new HashMap<String, Object>();
		boardCommentVO.setId(BOARDID);
		
		int result = 0;
		try {
			BoardCommentVO commentVO = boardCommentService.select(boardCommentVO);
			if (UserUtil.isEqualMember(commentVO.getUserId())) {
				result = boardCommentService.delete(boardCommentVO);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		status.setComplete();
		
		ret.put("result", result);
		
		return ret;
	}
	
	/**
	 * 첨부파일로 등록된 파일에 대하여 다운로드를 제공한다.
	 * 
	 * @param boardFileVO 게시판 파일 VO
	 * @param request Request 객체
	 * @param response Response 객체
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/download.do")
	public void cvplFileDownload(final BoardFileVO boardFileVO, final HttpServletRequest request, final HttpServletResponse response) throws Exception {
		boardFileVO.setId(BOARDID);
		
		BoardFileVO vo = boardFileService.select(boardFileVO);
		String fileOrgName = vo.getOrgName();
		String storePathKey = BoardUtils.getStorePathKey(boardFileVO.getId());
		String fileFullPath = propertiesService.getString(storePathKey) + vo.getSaveName();
		
		File file = new File(fileFullPath);
		if (file.exists()) {
			FileResponser.setResponse(file, fileOrgName, 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();
					}
				}
			}
		}
		
	}	
}
