package kcg.faics.tg.web;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
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 kcg.faics.cmmn.bbs.BaseBbsService;
import kcg.faics.cmmn.bbs.PageType;
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.LoginUserVO;
import kcg.faics.sec.UserUtil;
import kcg.faics.tg.service.impl.DivMngServiceImpl;
import kcg.faics.tg.vo.DivMngSearchVO;
import kcg.faics.tg.vo.DivMngVO;

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

/**
 * 외사분실운영현황 컨트롤러.
 * 
 * @author kimnomin
 *
 */
@Controller
@RequestMapping("/target/divmng")
public class DivMngController {
	/**
	 * properties값을 가져오는 인터페이스.
	 **/
	@Resource(name = "propertiesService")
	private EgovPropertyService propertiesService;

	/**
	 * message.properties의 값을 가져오는 인터페이스.
	 */
	@Autowired
	private MessageSource messageSource;
	
	/**
	 * Validator - 유효성 검사.
	 **/
	@Resource(name = "beanValidator")
	private DefaultBeanValidator beanValidator;

	/**
	 * 코드관련 정보 인터페이스.
	 */
	@Resource(name = "codeService")
	private CodeService codeService;
	
	/**
	 * 외사분실운영현황 비지니스 로직 클래스.
	 */
	@Resource(name = "divMngService")
	private BaseBbsService<DivMngSearchVO, DivMngVO> divMngService;
	
	/**
	 * Redirect URI를 조합하여 반환한다.
	 * 
	 * @param pageType
	 *            화면구분
	 * @param vo
	 *            외사분실운영현황 VO
	 * @return Redirect URI
	 */
	private String makeRedirectUri(final PageType pageType, final DivMngVO vo) {
		String uri = "redirect:/target/divmng";
		
		switch (pageType) {
		case View:
			uri = String.format("%s/view.do?place=%s&no=%s", uri, vo.getPlace(), vo.getNo());
			break;
		case List:
			uri = String.format("%s/list.do?place=%s", uri, vo.getPlace());
			break;
		default:
			break;
		}
		
		return uri;
	}
	
	/**
	 * 외사분실운영현황 정보 조회화면을 반환한다.
	 * 
	 * @param model
	 *            Model 객체
	 * @param divMngVO
	 *            외사분실운영현황 VO
	 * @return 외사분실운영현황 정보 조회화면
	 * @throws Exception
	 *             기본 예외 처리 
	 */
	@RequestMapping(value = "/view.do")
	public String view(final Model model, final DivMngVO divMngVO) throws Exception {
		LoginUserVO loginUserVO = UserUtil.getMemberInfo();
		model.addAttribute("loginUserVO", loginUserVO);
		
		DivMngVO vo = divMngService.select(divMngVO);
		model.addAttribute("divMngVO", vo);
		
		return "/tg/divMngView.tiles";
	}
	
	/**
	 * 외사분실운영현황 목록화면을 반환한다.
	 * 
	 * @param model
	 *            Model 객체
	 * @param locale
	 *            Locale 객체
	 * @param searchVO
	 *            검색조건 VO            
	 * @return 외사분실운영현황 목록화면
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/list.do")
	public String list(final Model model, final Locale locale,
			@ModelAttribute("searchVO") final DivMngSearchVO searchVO)
			throws Exception {
		LoginUserVO loginUserVO = UserUtil.getMemberInfo();
		model.addAttribute("loginUserVO", loginUserVO);
		
		List<CodeVO> placeList = codeService.getPlace1List(false, true);
		model.addAttribute("placeList", placeList);
		
		List<DivMngVO> divMngList = divMngService.selectList(searchVO);
		model.addAttribute("divMngList", divMngList);
		
		return "/tg/divMngList.tiles";
	}
	
	/**
	 * 외사분실운영현황 목록을 엑셀로 반환한다.
	 * 
	 * @param model
	 *            Model 객체
	 * @param locale
	 *            Locale 객체
	 * @param searchVO
	 *            검색조건 VO
	 * @return 외사분실운영현황 목록 엑셀
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/listtoexcel.do")
	public String listToExcel(final Model model, final Locale locale,
			@ModelAttribute("searchVO") final DivMngSearchVO searchVO)
			throws Exception {
		String title = messageSource.getMessage("target.divmng", null, locale);
		
		// 엑셀 헤더 생성
		LinkedHashMap<String, String> header = new LinkedHashMap<String, String>();
		header.put("placeStr", messageSource.getMessage("target.divmng.place", null, locale));
		header.put("local", messageSource.getMessage("target.divmng.local", null, locale));
		header.put("gubunStr", messageSource.getMessage("target.divmng.gubun", null, locale));
		header.put("staffNum", messageSource.getMessage("target.divmng.staffNum", null, locale));
		header.put("tel", messageSource.getMessage("target.divmng.tel", null, locale));
		
		// 데이터 생성
		List<DivMngVO> divMngList = divMngService.selectList(searchVO);
		
		// Export
		model.addAttribute("excel", new ExcelExporter<DivMngVO>(header, divMngList, title));
		model.addAttribute("filename", title);
		
		return "excelView";
	}
	
	/**
	 * 외사분실운영현황 입력화면을 반환한다.
	 * 
	 * @param model
	 *            Model 객체
	 * @param divMngVO
	 *            외사분실운영현황 VO
	 * @return 외사분실운영현황 입력화면
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/add.do")
	public String add(final Model model, final DivMngVO divMngVO)
			throws Exception {
		Boolean isAuthenticated = EgovUserDetailsHelper.isAuthenticated();

		if (isAuthenticated && UserUtil.isAdmin()) {
			LoginUserVO loginUserVO = UserUtil.getMemberInfo();
			model.addAttribute("loginUserVO", loginUserVO);
			model.addAttribute("registerFlag", "create");
			
			List<CodeVO> placeList = codeService.getPlace1List(false, false);
			model.addAttribute("placeList", placeList);
			
			divMngVO.setWriter(loginUserVO.getUserid());
			divMngVO.setPlace(loginUserVO.getPlace1());
			divMngVO.setPlaceStr(loginUserVO.getPlace1Str());
			
			return "/tg/divMngAdd.tiles";
		} else {
			return makeRedirectUri(PageType.List, divMngVO);
		}
	}
	
	/**
	 * 외사분실운영현황 정보를 입력한다.
	 *
	 * @param divMngVO
	 *            외사분실운영현황 VO
	 * @param bindingResult
	 *            BindingResult 객체
	 * @param model
	 *            Model 객체
	 * @param status
	 *            SessionStatus 객체
	 * @param multiRequest
	 *            MultipartHttpServletRequest 객체
	 * @return 외사분실운영현황 정보 조회화면
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/add.do", method = RequestMethod.POST)
	public String add(@ModelAttribute("divMngVO") final DivMngVO divMngVO,
			final BindingResult bindingResult, final Model model,
			final SessionStatus status,
			final MultipartHttpServletRequest multiRequest) throws Exception {
		// 사용자 인증 검사
		Boolean isAuthenticated = EgovUserDetailsHelper.isAuthenticated();
		if (isAuthenticated && UserUtil.isAdmin()) {
			// 유효성 검사
			beanValidator.validate(divMngVO, bindingResult);
			if (bindingResult.hasErrors()) {
				return add(model, divMngVO);
			}

			final Map<String, MultipartFile> fileMap = multiRequest.getFileMap();
			HashMap<String, Object> resultMap = divMngService.insert(divMngVO, fileMap);
			
			if ((Integer) resultMap.get("result") == 1) {
				status.setComplete();
				return makeRedirectUri(PageType.View, divMngVO);
			}
		}
		return "error/bizError";
	}
	
	/**
	 * 외사분실운영현황 수정화면을 반환한다.
	 * 
	 * @param divMngVO
	 *            외사분실운영현황 VO
	 * @param model
	 *            Model 객체
	 * @return 외사분실운영현황 수정화면
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/update.do")
	public String update(final DivMngVO divMngVO, final Model model) throws Exception {
		if (UserUtil.isAdmin()) {
			model.addAttribute("registerFlag", "modify");
			
			DivMngVO vo = divMngService.select(divMngVO);
			model.addAttribute("divMngVO", vo);
			
			LoginUserVO loginUserVO = UserUtil.getMemberInfo();
			model.addAttribute("loginUserVO", loginUserVO);
			
			return "/tg/divMngAdd.tiles";
		}
		
		return makeRedirectUri(PageType.View, divMngVO);
	}
	
	/**
	 * 외사분실운영현황 정보를 수정한다.
	 * 
	 * @param divMngVO
	 *            외사분실운영현황 VO
	 * @param bindingResult
	 *            BindingResult 객체
	 * @param model
	 *            Model 객체
	 * @param status
	 *            SessionStatus 객체
	 * @param multiRequest
	 *            MultipartHttpServletRequest 객체
	 * @return 외사분실운영현황 조회화면
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/update.do", method = RequestMethod.POST)
	public String update(@ModelAttribute("divMngVO") final DivMngVO divMngVO,
			final BindingResult bindingResult, final Model model,
			final SessionStatus status,
			final MultipartHttpServletRequest multiRequest) throws Exception {
		// 사용자 인증 검사
		Boolean isAuthenticated = EgovUserDetailsHelper.isAuthenticated();
		if (isAuthenticated && UserUtil.isAdmin()) {
			// 유효성 검사
			beanValidator.validate(divMngVO, bindingResult);
			if (bindingResult.hasErrors()) {
				return update(divMngVO, model);
			}
			
			String[] deleteFiles = multiRequest.getParameterValues("deleteFile");
			final Map<String, MultipartFile> fileMap = multiRequest.getFileMap();
			HashMap<String, Object> resultMap = divMngService.update(divMngVO, fileMap, deleteFiles);
			
			if ((Integer) resultMap.get("result") > 0) {
				status.setComplete();
				return makeRedirectUri(PageType.View, divMngVO);
			}
		}
		
		return update(divMngVO, model);
	}
	
	/**
	 * 외사분실운영현황 정보를 삭제한다.
	 * 
	 * @param divMngVO
	 *            외사분실운영현황 VO
	 * @param model
	 *            Model 객체
	 * @param status
	 *            SessionStatus 객체
	 * @return 외사분실운영현황 목록화면
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/delete.do", method = RequestMethod.POST)
	public String delete(final DivMngVO divMngVO, final Model model,
			final SessionStatus status) throws Exception {

		if (UserUtil.isAdmin()) {
			DivMngVO vo = divMngService.select(divMngVO);
			if (vo != null) {
				HashMap<String, Object> map = divMngService.delete(vo);
				if ((Integer) map.get("result") > 0) {
					return makeRedirectUri(PageType.List, vo);
				}
			}
		}
		
		return makeRedirectUri(PageType.View, divMngVO);
	}
	
	/**
	 * 파일을 반환한다.
	 * 
	 * @param divMngVO
	 *            외사분실운영현황 VO
	 * @param fileId
	 *            파일ID
	 * @param request
	 *            HttpServletRequest 객체
	 * @param response
	 *            HttpServletResponse 객체
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@RequestMapping(value = "/download.do")
	public void fileResponse(final DivMngVO divMngVO, final String fileId,
			final HttpServletRequest request, final HttpServletResponse response)
			throws Exception {
		DivMngVO vo = divMngService.select(divMngVO);
		String filename = "";
		if ("fileImg".equals(fileId)) {
			filename = vo.getFileImg();
		} else if ("file1".equals(fileId)) {
			filename = vo.getFile1();
		} else if ("file2".equals(fileId)) {
			filename = vo.getFile2();
		} else if ("file3".equals(fileId)) {
			filename = vo.getFile3();
		}

		if (StringUtils.isNotBlank(filename)) {
			String fileFullPath = propertiesService
					.getString(DivMngServiceImpl.FILE_PATH_KEYWORD) + filename;
			File file = new File(fileFullPath);
			if (file.exists()) {
				FileResponser.setResponse(file, filename, 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();
			}
		}
	}
}
