package kcg.faics.susa.web;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

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

import kcg.faics.cmmn.bbs.BaseBbsService;
import kcg.faics.cmmn.bbs.BaseFileService;
import kcg.faics.cmmn.excel.ExcelExporter;
import kcg.faics.cmmn.file.FileResponser;
import kcg.faics.cmmn.service.CodeService;
import kcg.faics.cmmn.vo.CodeVO;
import kcg.faics.sec.AuthType;
import kcg.faics.sec.LoginUserVO;
import kcg.faics.sec.UserUtil;
import kcg.faics.susa.vo.SearchVO;
import kcg.faics.susa.vo.SusaFileVO;
import kcg.faics.susa.vo.SusaVO;
import kcg.faics.susa.vo.IncidentVO;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
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.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;

/**
 * 내사사건현황 Controller.
 * 
 * @author kimnomin
 *
 */
@Controller
@RequestMapping("/susa/incident")
public class IncidentController {
	/**
	 * properties값을 가져오는 인터페이스.
	 **/
	@Resource(name = "propertiesService")
	private EgovPropertyService propertiesService;
	
	/**
	 * message.properties의 값을 가져오는 인터페이스.
	 */
	@Autowired
	private MessageSource messageSource;

	/**
	 * 코드관련 정보 인터페이스.
	 */
	@Resource(name = "codeService")
	private CodeService codeService;

	/**
	 * 외사수사 정보 인터페이스.
	 */
	@Resource(name = "susaService")
	private BaseBbsService<SearchVO, SusaVO> susaService;

	/**
	 * 사진 정보 인터페이스.
	 */
	@Resource(name = "incidentFileService")
	private BaseFileService<SusaFileVO> incidentFileService;

	/**
	 * Validator - 유효성 검사.
	 **/
	@Resource(name = "beanValidator")
	private DefaultBeanValidator beanValidator;

	/**
	 * 내사사건 목록 화면을 반환한다.
	 * 
	 * @param searchVO
	 *            검색, 페이지 정보 객체
	 * @param model
	 *            맵 객체
	 * @return 내사사건 목록 화면
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/list.do")
	public String list(@ModelAttribute("searchVO") final SearchVO searchVO,
			final ModelMap model) throws Exception {

		LoginUserVO loginUserVo = UserUtil.getMemberInfo();
		try {
			if (searchVO.getType() == null || searchVO.getType().isEmpty()) {
				searchVO.setType("in");
			}

			/* 페이징 처리 정보 */
			searchVO.setPageUnit(propertiesService.getInt("pageUnit"));
			searchVO.setPageSize(propertiesService.getInt("pageSize"));

			/* 페이징 처리 */
			PaginationInfo paginationInfo = new PaginationInfo();
			paginationInfo.setCurrentPageNo(searchVO.getPageIndex());
			paginationInfo.setRecordCountPerPage(searchVO.getRecordCountPerPage());
			paginationInfo.setPageSize(searchVO.getPageSize());

			List<CodeVO> placeList = null;
			if (AuthType.LOCAL_HEADQUARTERS == loginUserVo.getAuthType()) {
				placeList = codeService.getPlace1SubList(loginUserVo
						.getPlace1());
			} else {
				placeList = codeService.getPlace1List(false);
			}
			model.addAttribute("placeList", placeList);

			searchVO.setFirstIndex(paginationInfo.getFirstRecordIndex());
			searchVO.setLastIndex(paginationInfo.getLastRecordIndex());
			searchVO.setRecordCountPerPage(paginationInfo
					.getRecordCountPerPage());

			int totSearchCnt = susaService.selectListCnt(searchVO);
			paginationInfo.setTotalRecordCount(totSearchCnt);
			model.addAttribute("paginationInfo", paginationInfo);

			/* 게시판 리스트 */
			List<SusaVO> susaList = susaService.selectList(searchVO);
			model.addAttribute("susaList", susaList);

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

		} catch (Exception e) {
			e.printStackTrace();
			return "error/bizError";
		}

		return "susa/incidentList.tiles";
	}

	/**
	 * 내사사건 정보 조회 화면을 반환한다.
	 * 
	 * @param incidentVO
	 *            내사사건 VO
	 * @param model
	 *            모델 객체
	 * @return 내사사건 정보 조회 화면
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/view.do")
	public String view(final IncidentVO incidentVO, final Model model)
			throws Exception {
		SusaVO vo = susaService.select(incidentVO);
		vo.setPlace1Str(codeService.getPlace1Str(vo.getPlace1()));
		model.addAttribute("incidentVO", vo);

		SusaFileVO fileVO = new SusaFileVO();
		fileVO.setParentSeq(vo.getIdx());
		model.addAttribute("susaFileVO", incidentFileService.selectList(fileVO));

		LoginUserVO loginUserVo = UserUtil.getMemberInfo();
		model.addAttribute("loginUserVo", loginUserVo);

		return "susa/incidentView.tiles";
	}

	/**
	 * 내사사건 입력 화면을 반환한다.
	 * 
	 * @param model
	 *            모델 객체
	 * @param incidentVO
	 *            내사사건 VO
	 * @return 내사사건 입력 화면
	 */
	@RequestMapping(value = "/add.do")
	public String add(final Model model, final IncidentVO incidentVO) {
		LoginUserVO loginUserVo = UserUtil.getMemberInfo();
		IncidentVO vo;
		if (incidentVO == null) {
			vo = new IncidentVO();
		} else {
			vo = incidentVO;
		}
		vo.setPlace1(loginUserVo.getPlace1());
		vo.setWriter(loginUserVo.getUserid());

		model.addAttribute("incidentVo", incidentVO);
		model.addAttribute("loginUserVo", loginUserVo);
		/* create or modify 플래그 */
		model.addAttribute("registerFlag", "create");

		return "susa/incidentAdd.tiles";
	}

	/**
	 * 내사사건 정보를 입력한다.
	 * 
	 * @param multiRequest
	 *            mutipartform 객체
	 * @param incidentVO
	 *            내사수사 VO
	 * @param bindingResult
	 *            유효성 검사결과 객체
	 * @param model
	 *            모델 객체
	 * @param status
	 *            SessionStatus 객체
	 * @return 내사사건 정보 목록 화면
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/add.do", method = RequestMethod.POST)
	public String add(final MultipartHttpServletRequest multiRequest,
			@Valid @ModelAttribute("incidentVO") final IncidentVO incidentVO,
			final BindingResult bindingResult, final Model model,
			final SessionStatus status) throws Exception {

		// 사용자 인증 검사
		Boolean isAuthenticated = EgovUserDetailsHelper.isAuthenticated();
		if (isAuthenticated) {
			// 유효성 검사
			// beanValidator.validate(incidentVO, bindingResult);
			if (bindingResult.hasErrors()) {
				model.addAttribute("incidentVO", incidentVO);
				return "susa/incidentAdd.tiles";
			}

			LoginUserVO loginUserVO = UserUtil.getMemberInfo();
			incidentVO.setWriter(loginUserVO.getUserid());

			// 파일 저장 및 데이터 입력
			final Map<String, MultipartFile> fileMap = multiRequest.getFileMap();
			HashMap<String, Object> map = susaService.insert(incidentVO, fileMap);

			status.setComplete();

			int idx = (Integer) map.get("idx");
			int result = (Integer) map.get("result");
			if (result == 1 && idx > 0) {
				return "redirect:/susa/incident/view.do?idx=" + idx;
			}
		}

		return "error/bizError";
	}

	/**
	 * 내사사건 수정 화면을 반환한다.
	 * 
	 * @param incidentVO
	 *            내사수사 VO
	 * @param model
	 *            모델 객체
	 * @return 내사사건 수정 화면
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/update.do", method = RequestMethod.GET)
	public String update(final IncidentVO incidentVO, final Model model)
			throws Exception {
		try {
			SusaVO vo = susaService.select(incidentVO);

			/* 글 작성자와 세션 사용자의 아이디를 비교하여 본인여부를 판단한다 */
			if (vo == null || (!UserUtil.isEqualMember(vo.getWriter()) && !UserUtil.isAdmin())) {
				return "redirect:/susa/incident/view.do?idx=" + incidentVO.getIdx();
			}

			vo.setPlace1Str(codeService.getPlace1Str(vo.getPlace1()));
			model.addAttribute("incidentVO", vo);

			SusaFileVO fileVO = new SusaFileVO();
			fileVO.setParentSeq(vo.getIdx());
			model.addAttribute("susaFileVO", incidentFileService.selectList(fileVO));

			LoginUserVO loginUserVo = UserUtil.getMemberInfo();
			model.addAttribute("loginUserVo", loginUserVo);

			model.addAttribute("registerFlag", "modify");
		} catch (Exception e) {
			e.printStackTrace();
		}

		return "susa/incidentAdd.tiles";
	}

	/**
	 * 내사사건 정보를 수정한다.
	 * 
	 * @param multiRequest
	 *            mutipartform 객체
	 * @param incidentVO
	 *            내사수사 VO
	 * @param bindingResult
	 *            유효성 검사결과 객체
	 * @param model
	 *            모델 객체
	 * @param status
	 *            SessionStatus 객체
	 * @return 내사사건 정보 목록 화면
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/update.do", method = RequestMethod.POST)
	public String update(final MultipartHttpServletRequest multiRequest,
			@Valid @ModelAttribute("incidentVO") final IncidentVO incidentVO,
			final BindingResult bindingResult, final Model model,
			final SessionStatus status) throws Exception {
		try {
			SusaVO vo = susaService.select(incidentVO);			
			
			/* 글 작성자와 세션 사용자의 아이디를 비교하여 본인여부를 판단한다 */
			if (vo == null || (!UserUtil.isEqualMember(vo.getWriter()) && !UserUtil.isAdmin())) {
				return "redirect:/susa/incident/view.do?idx=" + incidentVO.getIdx();
			}
			
			// 유효성 검사
			if (bindingResult.hasErrors()) {
				model.addAttribute("incidentVO", incidentVO);
				model.addAttribute("registerFlag", "modify");
				return "susa/incidentAdd.tiles";
			}
			
			LoginUserVO loginUserVO = UserUtil.getMemberInfo();
			incidentVO.setWriter(loginUserVO.getUserid());
			
			String[] deleteFiles = multiRequest.getParameterValues("deleteFile");
			final Map<String, MultipartFile> fileMap = multiRequest.getFileMap();
			HashMap<String, Object> map = susaService.update(incidentVO, fileMap, deleteFiles);

			status.setComplete();
			
			int result = (Integer) map.get("result");
			int idx = (Integer) map.get("idx");
			
			if (result > 0 && idx > 0) {
				return "redirect:/susa/incident/view.do?idx=" + idx;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return "error/bizError";
		}
		
		return "error/bizError";
	}

	/**
	 * 내사사건 정보를 삭제한다.
	 * 
	 * @param incidentVO
	 *            내사수사 VO
	 * @param model
	 *            모델 객체
	 * @param status
	 *            SessionStatus 객체
	 * @return 내사사건 목록 화면
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/delete.do", method = RequestMethod.POST)
	public String delete(final IncidentVO incidentVO, final Model model,
			final SessionStatus status) throws Exception {
		SusaVO vo = susaService.select(incidentVO);

		/* 글 작성자와 세션 사용자의 아이디를 비교하여 본인여부를 판단한다 */
		if (vo == null || (!UserUtil.isEqualMember(vo.getWriter()) && !UserUtil.isAdmin())) {
			return "redirect:/susa/incident/view.do?idx=" + incidentVO.getIdx();
		}
		
		HashMap<String, Object> map = susaService.delete(incidentVO);
		if ((Integer) map.get("result") > 0) {
			return "redirect:/susa/incident/list.do";
		}
		return "redirect:/susa/incident/view.do?idx=" + incidentVO.getIdx();
	}
	
	/**
	 * 전체목록을 엑셀로 내보낸다.
	 *
	 * @param searchVO 검색조건 VO
	 * @param model Model 객체
	 * @param locale Locale 객체
	 * @return 엑셀(전체목록)
	 * @throws Exception 기본 예외 처리
	 */
	@RequestMapping(value = "/listtoexcel.do")
	public String exportExcel(@ModelAttribute("searchVO") final SearchVO searchVO, final Model model, final Locale locale) throws Exception {
		searchVO.setType("in");
		LinkedHashMap<String, String> header = new LinkedHashMap<String, String>();
		header.put("place1Str", messageSource.getMessage("susa.in.view.place1", null, locale));
		header.put("chargeNm", messageSource.getMessage("susa.in.view.chargeNm", null, locale));
		header.put("title", messageSource.getMessage("susa.in.view.title", null, locale));
		header.put("sdate", messageSource.getMessage("susa.in.view.sdate", null, locale));
		header.put("edate", messageSource.getMessage("susa.in.view.edate", null, locale));
		header.put("resultFlag", messageSource.getMessage("susa.in.view.result", null, locale));
		
		Date d = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String title = String.format("%s_%s", messageSource.getMessage("susa.in.view.pagetitle", null, locale), sdf.format(d));
		List<SusaVO> list = susaService.selectListAll(searchVO);
		
		model.addAttribute("excel", new ExcelExporter<SusaVO>(header, list, title));
		model.addAttribute("filename", title);
		
		return "excelView";
	}

	/**
	 * 파일을 반환한다.
	 * 
	 * @param susaFileVO
	 *            외사수사 파일 VO
	 * @param request
	 *            HttpServletRequest 객체
	 * @param response
	 *            HttpServletResponse 객체
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/download.do")
	public void fileResponse(final SusaFileVO susaFileVO,
			final HttpServletRequest request, final HttpServletResponse response) throws Exception {
		SusaFileVO vo = incidentFileService.select(susaFileVO);
		String fileOrgName = vo.getOrgName();
		String fileFullPath = propertiesService.getString("Susa.in.fileStorePath") + 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();
					}
				}
			}
		} else {
			response.setStatus(HttpStatus.NOT_FOUND.value());			
			throw new Exception();
		}
	}
}
