/** 
 * AdminServiceImpl.java
 * @author 임새미 
 * @since 2016. 10. 28.
 *
 *  	 수정일                     수정자                                       수정내용
 *  -------------	--------	---------------------------
 *  2016. 10. 28. 	    임새미				       최초생성
 * 
 */
package kcg.faics.member.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import kcg.faics.cmmn.egov.file.EgovFileMngUtil;
import kcg.faics.cmmn.file.FileUploadUtil;
import kcg.faics.cmmn.service.impl.CodeMapper;
import kcg.faics.member.UserType;
import kcg.faics.member.service.MemberService;
import kcg.faics.member.vo.ExMemberVO;
import kcg.faics.member.vo.MemberSearchVO;
import kcg.faics.member.vo.MemberVO;
import kcg.faics.sec.service.impl.SecurityMapper;

import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

/** 
 * 사용자 정보 비지니스로직.
 * 
 * AdminServiceImpl.java
 * @author 임새미 
 * @since 2016. 10. 28.
 *
 *  	 수정일                     수정자                                       수정내용
 *  -------------	--------	---------------------------
 *  2016. 10. 28. 	    임새미				       최초생성
 * 
 */
/**
 * @author kimnomin
 *
 */
@Service("memberService")
public class MemberServiceImpl implements MemberService {

	/**
	 * 사용자 Mapper 객체.
	 */
	@Resource(name = "memberMapper")
	private MemberMapper memberMapper;
	
	/**
	 * 시큐리티 Mapper 객체.
	 */
	@Resource(name = "securityMapper")
	private SecurityMapper securityMapper;
	
	/**
	 * 코드관련 Mapper 객체. 
	 */
	@Resource(name = "codeMapper")
	private CodeMapper codeMapper;
	
	/**
	 * 파일 업로드 유틸리티.
	 */
	@Resource(name = "fileUploadUtil")
	private FileUploadUtil fileUploadUtil;
	
	/**
	 * 전자정부 표준프레임워크 파일관리 유틸리티.
	 */
	@Resource(name = "EgovFileMngUtil")
	private EgovFileMngUtil fileMngUtil;
	
	/*@Resource(name = "passwordEncoder")
	private PasswordEncoder pwEncoder;*/
	
	/**
	 * 비밀번호 인코더.
	 */
	@Resource(name = "passwordEncoder")
	private ShaPasswordEncoder pwEncoder;
	
	/**
	 * 사용자 사진 저장 경로.
	 */
	private static final String USER_IMG_SAVE_PATH = "Member.imgStorePath";
	
	/**
	 * 사용자 서명 저장 경로. 
	 */
	private static final String USER_SIGN_SAVE_PATH = "Member.signStorePath";
	
	
	@Override
	public HashMap<String, Object> delete(final MemberVO dataVO, final String userType)
			throws Exception {
		HashMap<String, Object> resultMap = new HashMap<String, Object>();
		int result = 0;
		if (UserType.FA.equals(userType)) {
			result = memberMapper.deleteFaMemeber(dataVO); 
		} else if (UserType.CM.equals(userType)) {
			result = memberMapper.deleteCmmnMember(dataVO);
		}
		resultMap.put("result", result);
		return resultMap;
	}


	/**
	 * 선택한 사용자의 정보를 반환한다.
	 * 
	 * @param dataVO userid 
	 * @return 선택한 사용자 정보 반환
	 * @throws Exception 기본 예외 처리
	 */
	@Override
	public MemberVO select(final MemberVO dataVO) throws Exception {
		MemberVO result = memberMapper.getMember(dataVO);
		if (result != null) {
			result.setDutiesStr(codeMapper.getDutiesNameByCode(result.getDuties()));
			result.setPlace1Str(codeMapper.getPlace1NameByCode(result.getPlace1(), false));
			result.setPlace2Str(codeMapper.getPlace2NameByCode(result.getPlace1(), result.getPlace2()));
			result.setPlace3Str(codeMapper.getPlace3NameByCode(result.getPlace3()));
			result.setPositionStr(codeMapper.getPositionNameByCode(result.getPosition()));
			result.setScholarshipStr(codeMapper.getScholarshipNameByCode(result.getScholarship()));
			result.setJobtypeStr(codeMapper.getJobtypeNameByCode(result.getJobtype()));
		}
		return result;
	}

	
	@Override
	public List<MemberVO> selectListAll(final MemberSearchVO searchVO) throws Exception {
		if (UserType.FA.equals(searchVO.getUsertype())) {
			return this.getFaListAll(searchVO);
		} else {
			return memberMapper.getCmmnListAll(searchVO);
		}
	}

	/**
	 * 사용자 목록 화면을 반환한다.
	 * 
	 * @param searchVO 검색, 페이지 정보 객체
	 * @return 사용자 리스트
	 * @throws Exception 기본 예외 처리
	 */
	@Override
	public List<MemberVO> selectList(final MemberSearchVO searchVO) throws Exception {
		List<MemberVO> list = null;
		if (UserType.FA.equals(searchVO.getUsertype())) {
			list = memberMapper.getFaMemberList(searchVO);
		} else {
			list = memberMapper.getCmmnMemberList(searchVO);
		}
		return list;
	}

	/**
	 * 검색 키워드에 따른 총 사용자 목록을 조회한다.
	 * 
	 * @param searchVO 검색, 페이지 정보 객체
	 * @return 사용자 수
	 * @exception Exception 기본 예외 처리
	 */
	@Override
	public int selectListCnt(final MemberSearchVO searchVO) throws Exception {
		return memberMapper.selectListCnt(searchVO);
	}

	/**
	 * 전체 사용자 수 를 가져온다.
	 * 
	 * @return 사용자 수
	 * @throws Exception 기본 예외 처리
	 */
	@Override
	public int selectTotalCnt(final MemberSearchVO searchVO) throws Exception {
		return memberMapper.selectTotalCnt(searchVO);
	}

	/**
	 * 외사 경찰을 추가한다.
	 * 
	 * @param dataVO 사용자 정보 객체
	 * @param fileMap 업로드 파일정보
	 * @return HashMap/ seq : 게시물 , result : 성공 - 1, 실패 - 0
	 * @exception Exception 기본 예외 처리
	 */
	@Override
	@Transactional
	public HashMap<String, Object> insert(final MemberVO dataVO, final Map<String, MultipartFile> fileMap) throws Exception {
		
		if (fileMap != null && fileMap.get("img").getSize() > 0) {
			String userimg = fileUploadUtil.uploadWithExt(fileMap.get("img"), USER_IMG_SAVE_PATH);
			dataVO.setUserimg(userimg);
		}
		if (fileMap != null && fileMap.get("sign").getSize() > 0) {
			String usersign = fileUploadUtil.uploadWithExt(fileMap.get("sign"), USER_SIGN_SAVE_PATH);
			dataVO.setUsersign(usersign);
		}
		dataVO.setExcareer(dataVO.getExcareer_y() + "-" + dataVO.getExcareer_m());
		dataVO.setExcareer1(dataVO.getExcareer1_y() + "-" + dataVO.getExcareer1_m());
		dataVO.setExcareer2(dataVO.getExcareer2_y() + "-" + dataVO.getExcareer2_m());
		dataVO.setExcareer3(dataVO.getExcareer3_y() + "-" + dataVO.getExcareer3_m());
		
		// 보안솔루션 (CubeOne으로 처리)
		//dataVO.setPasswd(pwEncoder.encodePassword(dataVO.getPasswd(), null));
		
		HashMap<String, Object> result = new HashMap<String, Object>();
		upsertCareerStat(dataVO, true);
		result.put("result", memberMapper.insertFaMember(dataVO));
		result.put("userid", dataVO.getUserid());
		return result;
	}

	/**
	 * 사용자 정보를 업데이트 한다.
	 * 
	 * @param dataVO 사용자정보 VO
	 * @param fileMap MultipartFile형태의 파일정보 
	 * @param deleteFiles 삭제할 파일리스트
	 * @return HashMap/ seq : 게시물 번호 , result : 성공 - 1, 실패 - 0
	 */
	@Override
	public HashMap<String, Object> update(final MemberVO dataVO, final Map<String, MultipartFile> fileMap, final String[] deleteFiles) throws Exception {
		// userimg 삭제
		if (dataVO.getUserimg() != null && dataVO.getUserimg().equals("")) {
			fileMngUtil.deleteFile(dataVO.getUserimg(), USER_IMG_SAVE_PATH);
			dataVO.setUserimg(null);
		}
		// usersign 삭제
		if (dataVO.getUsersign() != null && dataVO.getUsersign().equals("")) {
			fileMngUtil.deleteFile(dataVO.getUsersign(), USER_SIGN_SAVE_PATH);
			dataVO.setUsersign(null);
		}
		
		if (fileMap != null && fileMap.get("img").getSize() > 0) {
			String userimg = fileUploadUtil.uploadWithExt(fileMap.get("img"), USER_IMG_SAVE_PATH);
			dataVO.setUserimg(userimg);
		}
		
		if (fileMap != null && fileMap.get("sign").getSize() > 0) {
			String usersign = fileUploadUtil.uploadWithExt(fileMap.get("sign"), USER_SIGN_SAVE_PATH);
			dataVO.setUsersign(usersign);
		}
		
		dataVO.setExcareer(dataVO.getExcareer_y() + "-" + dataVO.getExcareer_m());
		dataVO.setExcareer1(dataVO.getExcareer1_y() + "-" + dataVO.getExcareer1_m());
		dataVO.setExcareer2(dataVO.getExcareer2_y() + "-" + dataVO.getExcareer2_m());
		dataVO.setExcareer3(dataVO.getExcareer3_y() + "-" + dataVO.getExcareer3_m());
		
		if(dataVO.getPasswd() != null && !dataVO.getPasswd().equals("")) {
			// 보안솔루션 (CubeOne으로 처리)
			//dataVO.setPasswd(pwEncoder.encodePassword(dataVO.getPasswd(), null));
		}
		
		HashMap<String, Object> result = new HashMap<String, Object>();
		
		upsertCareerStat(dataVO, false);

		if (UserType.FA.equalsIgnoreCase(dataVO.getUsertype())) {
			result.put("result", memberMapper.updateFaMember(dataVO));	
		} else {
			result.put("result", memberMapper.updateCmmnMember(dataVO));
		}
		
		result.put("userid", dataVO.getUserid());
		return result;
	}
	
	@Override
	public HashMap<String, Object> updateFaMember(final MemberVO dataVO, final Map<String, MultipartFile> fileMap, final String[] deleteFiles)
			throws Exception {
		// userimg 삭제
		if (dataVO.getUserimg() != null && dataVO.getUserimg().equals("")) {
			fileMngUtil.deleteFile(dataVO.getUserimg(), USER_IMG_SAVE_PATH);
			dataVO.setUserimg(null);
		}
		// usersign 삭제
		if (dataVO.getUsersign() != null && dataVO.getUsersign().equals("")) {
			fileMngUtil.deleteFile(dataVO.getUsersign(), USER_SIGN_SAVE_PATH);
			dataVO.setUsersign(null);
		}
		
		if (fileMap != null && fileMap.get("img").getSize() > 0) {
			String userimg = fileUploadUtil.uploadWithExt(fileMap.get("img"), USER_IMG_SAVE_PATH);
			dataVO.setUserimg(userimg);
		}
		
		if (fileMap != null && fileMap.get("sign").getSize() > 0) {
			String usersign = fileUploadUtil.uploadWithExt(fileMap.get("sign"), USER_SIGN_SAVE_PATH);
			dataVO.setUsersign(usersign);
		}
		
		dataVO.setExcareer(dataVO.getExcareer_y() + "-" + dataVO.getExcareer_m());
		dataVO.setExcareer1(dataVO.getExcareer1_y() + "-" + dataVO.getExcareer1_m());
		dataVO.setExcareer2(dataVO.getExcareer2_y() + "-" + dataVO.getExcareer2_m());
		dataVO.setExcareer3(dataVO.getExcareer3_y() + "-" + dataVO.getExcareer3_m());
		
		if(dataVO.getPasswd() != null && !dataVO.getPasswd().equals("")) {
			// 보안솔루션 (CubeOne으로 처리)
			//dataVO.setPasswd(pwEncoder.encodePassword(dataVO.getPasswd(), null));
		}
		
		HashMap<String, Object> resultMap = new HashMap<String, Object>();
		upsertCareerStat(dataVO, false);
		int result = memberMapper.updateFaMember(dataVO);
		resultMap.put("result", result);		
		// 외사경찰 수정에 성공하고, 외사경찰이 일반경찰로 변경되었다면
		// 과거외사경찰 테이블에 입력 후 외사경찰 테이블에서 삭제한다. 
		if (result == 1 && UserType.CM.equals(dataVO.getUsertype())) {
			resultMap = moveFaMemberToExMember(dataVO);
		}
		resultMap.put("result", result);
		resultMap.put("userid", dataVO.getUserid());
		
		return resultMap;
	}

	/**
	 * 일반경찰을 등록한다. (기존에 등록된 일반경찰이면 삭제한 후 입력한다.)
	 * 
	 * @param dataVO
	 *            사용자 정보 VO
	 * @return 1-성공, 0-실패
	 * @throws Exception
	 *             기본 예외 처리
	 */
	public int insertCmmnMember(final MemberVO dataVO) throws Exception {
		delete(dataVO, UserType.CM);
		return memberMapper.insertCmmnMember(dataVO);
	}
	
	@Override
	public int updateCmmnMemberInfo(final MemberVO dataVO) throws Exception {
		return memberMapper.updateCmmnMemberInfo(dataVO);
	}

	@Override
	public HashMap<String, Object> delete(final MemberVO dataVO) throws Exception {
		return delete(dataVO, UserType.FA);
	}

	/**
	 * 사용자 비밀번호를 업데이트한다.
	 * 
	 * @param dataVO 사용자 정보 VO
	 * @return HashMap / match : 현재 비밀번호 일치 여부, result : 성공 - 1, 실패 - 0
	 * @throws Exception 기본 예외 처리
	 */
	@Override
	public HashMap<String, Object> updatePassword(final MemberVO dataVO) throws Exception {
		HashMap<String, Object> resultMap = new HashMap<String, Object>();
		int result = 0;

		MemberVO memberVO = memberMapper.getMember(dataVO);
		
		// 다르면 실패처리
		if (!pwEncoder.isPasswordValid(memberVO.getPasswd().toLowerCase(), dataVO.getPasswd(), null)) {
			resultMap.put("match", false);
		} else { 
			// 같으면 변겅처리
			dataVO.setPasswd(dataVO.getNpasswd());
			
			//// 보안솔루션 (CubeOne으로 처리)
			//dataVO.setPasswd(pwEncoder.encodePassword(dataVO.getNpasswd(), null));
			
			result = memberMapper.updatePassword(dataVO);
			resultMap.put("match", true);
		}
		resultMap.put("result", result);
		return resultMap;
	}
	
	/**
	 * 경력 정보를 업데이트 한다.
	 * 
	 * @param dataVO 사용자정보 VO
	 * @param isInsert 추가할지 삭제할지 여부
	 * @return HashMap/ result : 성공 - 1, 실패 - 0
	 * @throws Exception 기본 예외 처리
	 */
	private int upsertCareerStat(final MemberVO dataVO, final boolean isInsert) throws Exception {
		int result = 0;
		
		if (isInsert) {
			result = memberMapper.insertCareerStat(dataVO);
		} else {
			result = memberMapper.updateCareerStat(dataVO);
		}
		
		return result;
	}

	/**
	 * 비밀번호를 초기화한다.
	 * 
	 * @param dataVO 사용자 정보 VO
	 * @return HashMap / result : 성공 - 1, 실패 - 0
	 * @throws Exception 기본 예외 처리
	 */
	@Override
	@Transactional
	public HashMap<String, Object> initPassword(final MemberVO dataVO, final String[] users) throws Exception {
		HashMap<String, Object> resultMap = new HashMap<String, Object>();
		int result = 0;
		
		for (int i = 0; i < users.length; i++) {
			dataVO.setUserid(users[i]);
   			result = memberMapper.updatePassword(dataVO);
			
			if (result == 0) {
				throw new Exception();
			}
		}
		resultMap.put("result", result);
		return resultMap;
	}

	/**
	 * 외사경찰의 정원 및 현황을 가져온다.
	 * 
	 * @return 현황리스트
	 * @throws Exception 기본 예외 처리
	 */
	@Override
	public List<HashMap<String, Object>> getCapacityManagement() throws Exception {
		return memberMapper.getCapacityManagement();
	}
	
	/**
	 * 외사경력 현황을 가져온다.
	 * 
	 * @return 외사경력 현황리스트
	 * @throws Exception 기본 예외 처리
	 */
	@Override
	public List<HashMap<String, Object>> getCareerStatus() throws Exception {
		return memberMapper.getCareerStatus();
	}
	
	/**
	 * 과거외사경찰 목록을 가져온다.
	 * 
	 * @param memberSearchVO 검색, 페이지 정보 객체
	 * @return 과거외사경찰 리스트
	 * @throws Exception 기본 예외 처리
	 */
	@Override
	public List<HashMap<String, Object>> exmemberList(final MemberSearchVO memberSearchVO) throws Exception {
		return memberMapper.exmemberList(memberSearchVO);
	}
	
	@Override
	public List<ExMemberVO> exmemberVoList(final MemberSearchVO memberSearchVO)
			throws Exception {
		return memberMapper.exmemberVoList(memberSearchVO);
	}


	/**
	 * 검색 키워드에 따른 총 과거외사경찰 목록을 조회한다.
	 * 
	 * @param searchVO 검색, 페이지 정보 객체
	 * @return 사용자 수
	 * @exception Exception 기본 예외 처리
	 */
	@Override
	public int selectExmemberListCnt(final MemberSearchVO searchVO) throws Exception {
		return memberMapper.selectExmemberListCnt(searchVO);
	}

	/**
	 * 전체 과거외사경찰 사용자 수 를 가져온다.
	 * 
	 * @return 사용자 수
	 * @throws Exception 기본 예외 처리
	 */
	@Override
	public int selectExmemberTotalCnt(final MemberSearchVO searchVO) throws Exception {
		return memberMapper.selectExmemberTotalCnt(searchVO);
	}

	@Override
	public List<MemberVO> getFaListAll(final MemberSearchVO searchVO) throws Exception {
		if (StringUtils.isBlank(searchVO.getUsertype()) || StringUtils.isBlank(searchVO.getUserid())) {
			return memberMapper.getFaListAll(searchVO);
		} else {
			return memberMapper.getSearchMember(searchVO);
		}
	}


	@Override
	public HashMap<String, Object> failLogin(final MemberVO dataVO) throws Exception {
		MemberVO vo = select(dataVO);
		vo.setPasswd("");
		vo.incChkcnt();
		
		return update(vo, null, null);
	}


	@Override
	public HashMap<String, Object> initChkcnt(final MemberVO dataVO) throws Exception {
		MemberVO vo = select(dataVO);
		vo.setPasswd("");
		vo.setChkcnt(0);
		
		return update(vo, null, null);
	}

	@Override
	public ExMemberVO selectExMember(final ExMemberVO searchVO) throws Exception {
		return memberMapper.selectExMemeber(searchVO);
	}

	
	/**
	 * 외사경찰을 과거외사경찰로 이동한다.
	 * 
	 * @param dataVO
	 *            외사경찰 VO
	 * @return Map("result") = 1 : 성공, 0 : 실패
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@Transactional
	private HashMap<String, Object> moveFaMemberToExMember(final MemberVO dataVO) throws Exception {
		HashMap<String, Object> resultMap = new HashMap<String, Object>();
		dataVO.setUsertype(UserType.FA);
		MemberVO memberVO = select(dataVO);
		memberVO.setHashedPasswd(true);
		resultMap = insertExMember(memberVO);
		if ((Integer) resultMap.get("result") == 1) {
			resultMap.put("result", 0);
			resultMap = delete(dataVO);	
		}
		
		//20210224 최형석
		//만약 패스워드 입력안했으면..기존에 사용됬던 패스워드를 가져온다.
		if(dataVO.getPasswd().equals("") || dataVO.getPasswd() == null) {
			dataVO.setPasswd(memberVO.getPasswd()); 
		}
		
		int tmpResult = insertCmmnMember(dataVO);
		
		Object res = resultMap.get("result");
		if (res == null || (Integer) res != 1) {
			throw new Exception();
		}
		return resultMap;
	}
	
	/**
	 * 과거외사경찰을 외사경찰로 이동한다.
	 * 
	 * @param dataVO
	 *            과거외사경찰 VO
	 * @return Map("result") = 1 : 성공, 0 : 실패
	 * @throws Exception
	 *             기본 예외 처리
	 */
	@Transactional
	private HashMap<String, Object> moveExMemberToFaMember(final ExMemberVO dataVO) throws Exception {
		HashMap<String, Object> resultMap = new HashMap<String, Object>();
		ExMemberVO updatedVO = selectExMember(dataVO);
		updatedVO.setHashedPasswd(true);
		resultMap = insert(updatedVO, null);
		if ((Integer) resultMap.get("result") == 1) {
			resultMap.put("result", 0);
			resultMap = deleteExMember(updatedVO);	
		}
		
		Object res = resultMap.get("result");
		if (res == null || (Integer) res < 1) {
			throw new Exception();
		}
		return resultMap;
	}
	
	/**
	 * 과거외사경찰 정보를 입력한다.
	 * 
	 * @param dataVO
	 *            과거외사경찰 VO
	 * @return Map("result") = 1 : 성공, 0 : 실패
	 * @throws Exception
	 *             기본 예외 처리
	 */
	private HashMap<String, Object> insertExMember(final ExMemberVO dataVO) throws Exception {
		HashMap<String, Object> resultMap = new HashMap<String, Object>();
		int result = memberMapper.insertExMemeber(dataVO);
		resultMap.put("result", result);
		return resultMap;
	}
	
	/**
	 * 과거외사경찰 정보를 입력한다.
	 * 
	 * @param dataVO
	 *            외사경찰 VO
	 * @return Map("result") = 1 : 성공, 0 : 실패
	 * @throws Exception
	 *             기본 예외 처리
	 */
	private HashMap<String, Object> insertExMember(final MemberVO dataVO) throws Exception {
		HashMap<String, Object> resultMap = new HashMap<String, Object>();
		int result = memberMapper.insertExMemeber(dataVO);
		resultMap.put("result", result);
		return resultMap;
	} 
	
	@Override
	public HashMap<String, Object> updateExMember(final ExMemberVO dataVO)
			throws Exception {
		
		String savedImgName = "";
		if (dataVO.getImg() != null && dataVO.getImg().getSize() > 0) {
			savedImgName = fileUploadUtil.uploadWithExt(dataVO.getImg(), USER_IMG_SAVE_PATH);
			dataVO.setUserimg(savedImgName);
		}
		
		HashMap<String, Object> resultMap = new HashMap<String, Object>();
		int result = memberMapper.updateExMember(dataVO);
		resultMap.put("result", result);
		// 과거외사경찰 수정에 성공하고, 과거외사경찰(현재는 일반경찰)이 외사경찰로 변경되었다면
		// 외사경찰 테이블에 입력 후 과거외사경찰 테이블에서 삭제한다. 
		if (result >= 1 && UserType.FA.equals(dataVO.getUsertype())) {
			resultMap = moveExMemberToFaMember(dataVO);
		}
		resultMap.put("result", result);
		return resultMap;
	}

	@Override
	public HashMap<String, Object> deleteExMember(final ExMemberVO dataVO)
			throws Exception {
		HashMap<String, Object> resultMap = new HashMap<String, Object>();
		resultMap.put("result", memberMapper.deleteExMemeber(dataVO));
		return resultMap;
	}
	
	
}
