package itn.let.mjo.msgcampain.web;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

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

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import egovframework.rte.fdl.idgnr.EgovIdGnrService;
import egovframework.rte.fdl.security.userdetails.util.EgovUserDetailsHelper;
import egovframework.rte.psl.dataaccess.util.EgovMap;
import egovframework.rte.ptl.mvc.tags.ui.pagination.PaginationInfo;
import itn.com.cmm.ComDefaultCodeVO;
import itn.com.cmm.EgovMessageSource;
import itn.com.cmm.JsonResult;
import itn.com.cmm.LoginVO;
import itn.com.cmm.service.EgovCmmUseService;
import itn.com.cmm.service.EgovFileMngService;
import itn.com.cmm.service.EgovFileMngUtil;
import itn.com.cmm.util.MJUtil;
import itn.com.cmm.util.RedirectUrlMaker;
import itn.com.cmm.util.StringUtil;
import itn.com.utl.fcc.service.EgovStringUtil;
import itn.let.lett.service.HashConfVO;
import itn.let.lett.service.LetterService;
import itn.let.lett.service.LetterVO;
import itn.let.mjo.addr.service.AddrGroupService;
import itn.let.mjo.addr.service.AddrService;
import itn.let.mjo.addr.service.AddrVO;
import itn.let.mjo.event.service.MjonEventService;
import itn.let.mjo.event.service.MjonEventVO;
import itn.let.mjo.msg.service.MjonMsgService;
import itn.let.mjo.msgcampain.service.MjonCandidateService;
import itn.let.mjo.msgcampain.service.MjonCandidateTWVO;
import itn.let.mjo.msgcampain.service.MjonCandidateVO;
import itn.let.mjo.msgdata.service.MjonMsgDataService;
import itn.let.mjo.msgdata.service.MjonMsgDataVO;
import itn.let.mjo.msgdata.service.PhoneVO;
import itn.let.mjo.pay.service.MjonPayService;
import itn.let.mjo.spammsg.service.MjonSpamMsgService;
import itn.let.mjo.symbol.service.MjonSymbolService;
import itn.let.mjo.symbol.service.MjonSymbolVO;
import itn.let.sym.ccm.cde.service.CateCode;
import itn.let.sym.ccm.cde.service.EgovCcmCmmnDetailCodeManageService;
import itn.let.sym.grd.service.MberGrdService;
import itn.let.sym.site.service.EgovSiteManagerService;
import itn.let.sym.site.service.JoinSettingVO;
import itn.let.uss.umt.service.EgovMberManageService;
import itn.let.uss.umt.service.EgovUserManageService;
import itn.let.uss.umt.service.MberManageVO;
import itn.let.utl.fcc.service.EgovCryptoUtil;

@Controller
public class MjonMsgCampainTWDataController {

	@Resource(name = "mjonMsgService")
    private MjonMsgService mjonMsgService;
	
	@Resource(name = "mjonPayService")
    private MjonPayService mjonPayService;
	
	@Resource(name = "MjonMsgDataService")
    private MjonMsgDataService mjonMsgDataService;
	
	@Resource(name = "LetterService")
    private LetterService letterService;
	
	@Resource(name = "mjonSymbolService")
	private MjonSymbolService mjonSymbolService;
	
	/** mberManageService */
	@Resource(name = "mberManageService")
	private EgovMberManageService mberManageService;
	
	@Resource (name = "AddrService")
	private AddrService addrService;
	
	@Resource (name = "AddrGroupService")
	private AddrGroupService addrGroupService;
	
	@Resource(name = "mjonCandidateService")
    private MjonCandidateService mjonCandidateService;
	
	@Resource(name = "EgovCmmUseService")
	private EgovCmmUseService cmmUseService;
	
	/** EgovMessageSource */
    @Resource(name="egovMessageSource")
    EgovMessageSource egovMessageSource;
    
    @Resource(name="EgovFileMngUtil")
	private EgovFileMngUtil fileUtil;
    
    @Resource(name="EgovFileMngService")
    private EgovFileMngService fileMngService;
    
    /* 암복호화 */
	@Resource(name = "egovCryptoUtil")
	EgovCryptoUtil egovCryptoUtil;
	
    @Resource(name = "egovMjonMsgGroupIdGnrService")
    private EgovIdGnrService idgenMjonMsgGroupId;
    
	@Resource(name = "egovMjonCashIdGnrService")
    private EgovIdGnrService idgenMjonCashId;
	
	@Resource(name = "CmmnDetailCodeManageService")
    private EgovCcmCmmnDetailCodeManageService cmmnDetailCodeManageService;
	
	/** 첨부파일 저장경로 */
	@Value("#{globalSettings['Globals.file.saveDir']}")
	private String fileSaveDir;
    
	/** userManageService */
	@Resource(name = "userManageService")
	private EgovUserManageService userManageService;
	
	@Resource(name = "MjonEventService")
    private MjonEventService mjonEventService;
	
	@Resource(name = "mjonSpamMsgService")
    private MjonSpamMsgService mjonSpamMsgService;
    
	/** 사이트 설정 */ 
	@Resource(name = "egovSiteManagerService")
	EgovSiteManagerService egovSiteManagerService;
	
	/** 등급제 관리 서비스 */
	@Resource(name = "mberGrdService")
	MberGrdService mberGrdService;
	
    /**
     * 선거 문자 20건씩 발송 화면 
     * @param searchVO
     * @param model
     * @return	"/web/mjon/msgcampain/selectMsgTWDataView.do"
     * @throws Exception
     */
	@RequestMapping(value= {"/web/mjon/msgcampain/selectMsgTWDataView.do"})
	public String selectMsgTWDataView(@ModelAttribute("searchVO") MjonMsgDataVO searchVO
			, CateCode cateCode
			, HttpServletRequest request
			, ModelMap model) throws Exception{
		
		String categoryType = cateCode.getCateType();
		
		if(categoryType == null) {
			
			categoryType = "N";
			
		}
		
		// 문자 카테고리 리스트 불러오기
		List<CateCode> cateConfList = letterService.selectCateConfWithList(categoryType);
		model.addAttribute("cateCodeList", cateConfList);	
		
		// 문자 해쉬태그 리스트 불러오기
		String msgType = "M";
		List<HashConfVO> hashTagList = letterService.selectHashTagWithList(msgType);
		model.addAttribute("hashTagList", hashTagList);
		
		// 문자 리스트 불러오기
		LetterVO letterVO = new LetterVO();
		if(letterVO.getPageUnit() != 10) {
			letterVO.setPageUnit(letterVO.getPageUnit());
		}
		
		//로그인 권한정보 불러오기
		LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
		model.addAttribute("loginVO", loginVO);
		
		for(int i=0 ; i < cateConfList.size(); i++) {
			if("선거".equals(cateConfList.get(i).getCateNm())) {
				letterVO.setCategoryCode(cateConfList.get(i).getCateCode());
			}
		}
		
		//주소록에서 선택시 넘어오는 파라미터
		if("Y".equals(searchVO.getMoveAddrFlag())) {
			model.addAttribute("addrVO", searchVO);
		}
		
		//주소록에서 선택시 넘어오는 파라미터
		if("Y".equals(searchVO.getMoveAddrAllFlag())) {
			AddrVO addrVO = new AddrVO();
			
			String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());
			if(userId != "") {
				addrVO.setMberId(userId);
			} 
			addrVO.setRecordCountPerPage(100000);
			addrVO.setFirstIndex(0);
			addrVO.setSearchAddrGrpId(request.getParameter("searchAddrGrpId"));
			addrVO.setSearchCondition(request.getParameter("searchCondition"));
			addrVO.setSearchKeyword(request.getParameter("searchKeyword"));	
			addrVO.setStartKeyword(request.getParameter("startKeyword"));
			List<AddrVO> addrList = addrService.selectAddrList(addrVO);
			
			List<String> addrIdList = new ArrayList<String>();
			for(AddrVO item : addrList) {
				addrIdList.add(item.getAddrId());
			}
			
			searchVO.setAddrIdList(addrIdList);
			searchVO.setMoveAddrFlag("Y");
			
			model.addAttribute("addrVO", searchVO);
		}				
		
		/** pageing */
		PaginationInfo paginationInfo = new PaginationInfo();
		paginationInfo.setCurrentPageNo(letterVO.getPageIndex());
		paginationInfo.setRecordCountPerPage(letterVO.getPageUnit());
		paginationInfo.setPageSize(letterVO.getPageSize());

		letterVO.setFirstIndex(paginationInfo.getFirstRecordIndex());
		letterVO.setLastIndex(paginationInfo.getLastRecordIndex());
		letterVO.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());
		
		
		List<?> resultPhoList = mjonMsgDataService.selectPhotoLetterList(letterVO);
		
		model.addAttribute("resultPhoList", resultPhoList);
		paginationInfo.setTotalRecordCount( resultPhoList.size()> 0 ? ((Long)((EgovMap)resultPhoList.get(0)).get("totCnt")).intValue() : 0);
		model.addAttribute("paginationInfo", paginationInfo);
		
		//발송결과 문자 재전송에서 넘어오는 경우 파마리터 전달
		List<String> temp = searchVO.getMsgSeqList();
		
		if(temp != null) {
			
			model.addAttribute("reSendMsgVO", searchVO);
			
		}
		model.addAttribute("letterVO", letterVO);
		
		// 문자 재전송 New
		model.addAttribute("msgResendAllFlag", searchVO.getMsgResendAllFlag());
		model.addAttribute("msgResendAllGroupId", searchVO.getMsgResendAllGroupId());
		model.addAttribute("msgResendAllAdvertiseYn", searchVO.getMsgResendAllAdvertiseYn());
		model.addAttribute("msgResendAllReplaceYn", searchVO.getMsgResendAllReplaceYn());
		
		return "web/msgcampain/tw/MsgTWDataView";
	}
	
	 /**
     * 선거 문자 20건씩 발송 단문/장문/그림문자 전송 화면 
     * @param searchVO
     * @param model
     * @return	"/web/mjon/msgcampain/selectMsgTWDataSMLViewAjax.do"
     * @throws Exception
     */
	@RequestMapping(value= {"/web/mjon/msgcampain/selectMsgTWDataSMLViewAjax.do"})
	public String selectMsgTWDataSMLView(@ModelAttribute("searchVO") MjonMsgDataVO searchVO, CateCode cateCode, ModelMap model) throws Exception{
		
		//로그인 권한정보 불러오기
    	LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
    	String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());
    	String author = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getAuthority());
    	
		String categoryType = cateCode.getCateType();
		
		if(categoryType == null) {
			
			categoryType = "N";
			
		}
		
		//문자 전송 개인 단가 불러오기
		
		//0.이벤트 진행중이 회원 정보 불러오기.
		//이벤트 회원 정보 테이블에서 대상자의 정보를 불러온다.
		MjonEventVO mjonEventVO = new MjonEventVO();
		mjonEventVO.setMberId(userId);
		MjonEventVO eventMberInfo = mjonEventService.selectEventMsgMberDefaultInfo(mjonEventVO);
		
		
		long eventDiffDate = 0;
		float eventRemainCash = 0;
		boolean compareEndDate = false;
		
		if(eventMberInfo != null) {
			
			String eventEndDate = eventMberInfo.getEventEndDate();
			
			/**
			 * MJUtil.getCompareDate()
			 * 현재 날짜와 파라미터 전달 날짜를 비교
			 * 전달날짜를 지난경우 False를 리턴함.
			 * 현재날짜 이전 혹은 같은 날짜면 True를 리턴함.
			 * 
			 * */
			
			if(eventEndDate != null) {
				compareEndDate = MJUtil.getCompareDate(eventEndDate);
				eventRemainCash = (float) eventMberInfo.getEventRemainCash(); 
				
				//이벤트 종료 일자가 지난 경우, 이벤트 상태가 종료아 아니면 종료 처리 시킴
				//이벤트 남은 캐시가 단문 발송금액 7.5원 보다 낮으면 이벤트 종료 시킴
				if(!compareEndDate || eventRemainCash < 7.5) {
					
					if(!eventMberInfo.getEventStatus().equals("E")) {
						
						//이벤트 상태값을 종료로 변경한다.
						mjonEventVO.setEventInfoId(eventMberInfo.getEventInfoId());
						mjonEventVO.setEventStatus("E");
						mjonEventVO.setEventMemo("이벤트 발송 최소 금액(7.5) 부족 혹은 이벤트 종료일 초과되어 이벤트 종료 시킴");
						mjonEventVO.setEventRemainCash(eventRemainCash);
						mjonEventService.updateEventEndStatus(mjonEventVO);
						eventMberInfo.setEventStatus("E");
						
					}
					
				}else {//이벤트 진행중이면 남은 날짜 계산해서 전달.
					
					/**
					 * MJUtil.getDiffDateDay()
					 * 현재 날짜와 파라미터 날짜 사이의 날짜 수를 계산해줌.
					 * 
					 * */
					eventDiffDate = MJUtil.getDiffDateDay(eventEndDate);
					
				}
			}
			
		}
		
		//남은 날짜값을 절대값으로 변경(음수로 나오기 때문)
		model.addAttribute("eventDiffDate", Math.abs(eventDiffDate));
		model.addAttribute("compareEndDate", compareEndDate);
		model.addAttribute("eventRemainCash", eventRemainCash);
		model.addAttribute("eventMberInfo", eventMberInfo);
		
		//1.시스템 기본 단가 정보 불러오기
		JoinSettingVO sysJoinSetVO = mjonMsgDataService.selectJoinSettingInfo();
		
		// 등급제 단가 추출 => 시스템 단가에 적용
		sysJoinSetVO = mberGrdService.selectMberGrdDefaultInfo(sysJoinSetVO, userId);
		
		//2.사용자 개인 단가 정보 불러오기
		MberManageVO mberManageVO = new MberManageVO(); 
		
		if(!userId.equals("") && !author.equals("ROLE_ADMIN")) {
			
			mberManageVO = mjonMsgDataService.selectMberManageInfo(userId);
			searchVO.setUserId(userId);
			
		}
		
		model.addAttribute("exceptSpamYn", mberManageVO.getExceptSpamYn());
		
		//3.사용자 개인단가 정보가 0이 아니면 개인단가 사용, 없으면 시스템 기본 단가 사용
		Float shortPrice = mberManageVO.getShortPrice();
		Float longPrice = mberManageVO.getLongPrice();
		Float picturePrice = mberManageVO.getPicturePrice();
		Float picture2Price = mberManageVO.getPicture2Price();
		Float picture3Price = mberManageVO.getPicture3Price();
		BigDecimal userMoney = new BigDecimal(mberManageVO.getUserMoney()).setScale(2, RoundingMode.HALF_EVEN);
		
		//일반 단가정보 저장 변수 셋팅 - 이벤트 캐시 부족시 일반단가로 계산하기 위해서임.20230328, 우영두추가
		Float norShortPrice = mberManageVO.getShortPrice();
		Float norLongPrice = mberManageVO.getLongPrice();
		Float norPicturePrice = mberManageVO.getPicturePrice();
		Float norPicture2Price = mberManageVO.getPicture2Price();
		Float norPicture3Price = mberManageVO.getPicture3Price();
		
		//기존 소수점 2째자리에서 반올림하였으나, 정책 변경으로 소수점 버림 처리함 20220623 
		/*int shortPrice = (int) mberManageVO.getShortPrice();
		int longPrice = (int) mberManageVO.getLongPrice();
		int picturePrice = (int) mberManageVO.getPicturePrice();
		int picture2Price = (int) mberManageVO.getPicture2Price();
		int picture3Price = (int) mberManageVO.getPicture3Price();
		int userMoney = (int) mberManageVO.getUserMoney();*/
		
		String userPoint = mberManageVO.getUserPoint();
		
		//이벤트 진행 회원의 발송 단가 처리해주기
		if(eventMberInfo != null && eventMberInfo.getEventStatus().equals("Y") && compareEndDate) {
			
			shortPrice = Float.parseFloat(eventMberInfo.getEventShortPrice());
			longPrice = Float.parseFloat(eventMberInfo.getEventLongPrice());
			picturePrice = Float.parseFloat(eventMberInfo.getEventPicturePrice());
			picture2Price = Float.parseFloat(eventMberInfo.getEventPicture2Price());
			picture3Price = Float.parseFloat(eventMberInfo.getEventPicture3Price());
			
			//이벤트 캐시 부족시 일반단가로 계산하기 위해서임.20230328, 우영두추가
			if(shortPrice < 1 || longPrice < 1 || picturePrice < 1) {//이벤트 단가 적용시 일반단가도 필요하여 셋팅 해줌.
				
				norShortPrice = (float) sysJoinSetVO.getShortPrice();
				norLongPrice = (float) sysJoinSetVO.getLongPrice();
				norPicturePrice = (float) sysJoinSetVO.getPicturePrice();
				norPicture2Price = (float) sysJoinSetVO.getPicture2Price();
				norPicture3Price = (float) sysJoinSetVO.getPicture3Price();
				
			}
			
		}else if(shortPrice < 1 || longPrice < 1 || picturePrice < 1) {
			
			shortPrice = (float) sysJoinSetVO.getShortPrice();
			longPrice = (float) sysJoinSetVO.getLongPrice();
			picturePrice = (float) sysJoinSetVO.getPicturePrice();
			picture2Price = (float) sysJoinSetVO.getPicture2Price();
			picture3Price = (float) sysJoinSetVO.getPicture3Price();
			
		}
		
		model.addAttribute("shortPrice", shortPrice);
		model.addAttribute("longPrice", longPrice);
		model.addAttribute("picturePrice", picturePrice);
		model.addAttribute("picture2Price", picture2Price);
		model.addAttribute("picture3Price", picture3Price);
		model.addAttribute("userMoney", userMoney);
		model.addAttribute("userPoint", userPoint);
		
		//이벤트 캐시 부족시 일반단가로 계산하기 위해서임.20230328, 우영두추가
		if(norShortPrice < 1 || norLongPrice < 1 || norPicturePrice < 1) {//협의 단가가 없는 경우 일반단가에 시스템 단가로 셋팅해줌
			
			norShortPrice = (float) sysJoinSetVO.getShortPrice();
			norLongPrice = (float) sysJoinSetVO.getLongPrice();
			norPicturePrice = (float) sysJoinSetVO.getPicturePrice();
			norPicture2Price = (float) sysJoinSetVO.getPicture2Price();
			norPicture3Price = (float) sysJoinSetVO.getPicture3Price();
			
		}
		
		model.addAttribute("norShortPrice", norShortPrice);
		model.addAttribute("norLongPrice", norLongPrice);
		model.addAttribute("norPicturePrice", norPicturePrice);
		model.addAttribute("norPicture2Price", norPicture2Price);
		model.addAttribute("norPicture3Price", norPicture3Price);
		
		//선거 후보자 정보 불러오기
		MjonCandidateVO mjonCandidateVO = new MjonCandidateVO();
		
		if(userId != ""){
			
			mjonCandidateVO = mjonCandidateService.selectCandidateDataInfo(userId);
			
			//String cryptText = egovCryptoUtil.encrypt(plainText);

			if(mjonCandidateVO != null) {
				
				// 주민번호 복호화 하기
				String regidentNo1 = egovCryptoUtil.decrypt(mjonCandidateVO.getRegidentNo1());
		    	String regidentNo2 = egovCryptoUtil.decrypt(mjonCandidateVO.getRegidentNo2());
		    	
		    	mjonCandidateVO.setRegidentNo1(regidentNo1);
		    	mjonCandidateVO.setRegidentNo2(regidentNo2);
				
			}
			
		}
		
		model.addAttribute("mjonCandidateVO", mjonCandidateVO);
		
		// 이메일 코드조회
		ComDefaultCodeVO voComCode = new ComDefaultCodeVO();
		voComCode.setCodeId("ITN031");
		model.addAttribute("emailCode", cmmUseService.selectCmmCodeDetail(voComCode));
		
		if(!userId.equals("")) {//로그인 했을때만 발신번호 리스트 불러오기
			
			//아이디 발신번호 리스트 불러오기.
			List<String> resultSendPhonList = mjonMsgDataService.selectSendPhonNumList(userId);
			List<String> resultPhonList = new ArrayList<String>();
			MJUtil mjUtil = new MJUtil();
			
			for(String phone : resultSendPhonList) {
				
				resultPhonList.add(mjUtil.addDash(phone));
				
			}
			model.addAttribute("resultPhonList", resultPhonList);
			
		}
		
		// 문자 카테고리 리스트 불러오기
		List<CateCode> cateConfList = letterService.selectCateConfWithList(categoryType);
		model.addAttribute("cateCodeList", cateConfList);	
		
		//그림 문자 리스트 불러오기
		LetterVO letterVO = new LetterVO();
		if(letterVO.getPageUnit() != 10) {
			letterVO.setPageUnit(letterVO.getPageUnit());
		}
		
		MjonSymbolVO symbolVO = new MjonSymbolVO();
		// 특수문자 리스트 불러오기
		List<MjonSymbolVO> symbolList = mjonSymbolService.selectMjonSymbolList(symbolVO);
		model.addAttribute("symbolList", symbolList);
		
		//최근 전송 내역
		Calendar cal = Calendar.getInstance();
    	Date now = new Date();
    	
    	SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
    	
    	cal.setTime(now);
    	cal.add(Calendar.DATE, -3);
    	
    	String chkDate = format.format(cal.getTime());
    	
    	searchVO.setMyMsgStDt(chkDate);	//검색 시작일 저장 - 현재날짜로 부터 3일 이전 날짜로 시작
		List<?> resultLatestMsgList = mjonMsgDataService.selectLatestMsgList(searchVO);
		model.addAttribute("resultLatestMsgList", resultLatestMsgList);
		
		//자주보내는 번호
		List<?> resultBookMarkMsgList = mjonMsgDataService.selectBookMarkMsgList(searchVO);
		model.addAttribute("resultBookMarkMsgList", resultBookMarkMsgList);
		

		/** pageing */
		PaginationInfo paginationInfo = new PaginationInfo();
		paginationInfo.setCurrentPageNo(letterVO.getPageIndex());
		paginationInfo.setRecordCountPerPage(letterVO.getPageUnit());
		paginationInfo.setPageSize(letterVO.getPageSize());

		letterVO.setFirstIndex(paginationInfo.getFirstRecordIndex());
		letterVO.setLastIndex(paginationInfo.getLastRecordIndex());
		letterVO.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());
		
		List<?> resultPhoList = mjonMsgDataService.selectPhotoLetterList(letterVO);
		
		model.addAttribute("resultPhoList", resultPhoList);
		paginationInfo.setTotalRecordCount( resultPhoList.size()> 0 ? ((Long)((EgovMap)resultPhoList.get(0)).get("totCnt")).intValue() : 0);
		model.addAttribute("paginationInfo", paginationInfo);
		model.addAttribute("mberManageVO", mberManageVO);
		
		//기존 작업하던 수신목록 정보가 있는지 확인
		int callSeq = mjonCandidateService.selectMsgCallToSeqNum(userId);
		model.addAttribute("callSeq", callSeq);
		
		return "web/msgcampain/tw/MsgTWDataSMLView";
	}
	
	//선거문자 20건 받는사람 목록 불러오기
	@RequestMapping(value="/web/mjon/msgcampain/selectMsgTWCallToListAjax.do")
	public String selectMsgTWCallToListAjax(MjonCandidateTWVO mjonCandidateTWVO, ModelMap model, RedirectAttributes redirectAttributes) throws Exception{
		
		
		//로그인 권한정보 불러오기
    	LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
    	String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());
    	
    	if(userId.equals("")) {
    		
    		redirectAttributes.addFlashAttribute("message", "로그인이 필요합니다.");
			RedirectUrlMaker redirectUrlMaker = new RedirectUrlMaker("/web/user/login/login.do");
			return redirectUrlMaker.getRedirectUrl();
    		
    	}
		
		/** pageing */
		PaginationInfo paginationInfo = new PaginationInfo();
		paginationInfo.setCurrentPageNo(mjonCandidateTWVO.getPageIndex());
		paginationInfo.setRecordCountPerPage(mjonCandidateTWVO.getPageUnit());
		paginationInfo.setPageSize(5);

		mjonCandidateTWVO.setFirstIndex(paginationInfo.getFirstRecordIndex());
		mjonCandidateTWVO.setLastIndex(paginationInfo.getLastRecordIndex());
		mjonCandidateTWVO.setRecordCountPerPage(20);
		
		mjonCandidateTWVO.setMberId(userId);
		List<?> resultCallToList = mjonCandidateService.selectCampainTWCalltoList(mjonCandidateTWVO);
		
		model.addAttribute("resultCallToList", resultCallToList);
		paginationInfo.setTotalRecordCount( resultCallToList.size()> 0 ? ((Long)((EgovMap)resultCallToList.get(0)).get("totCnt")).intValue() : 0);
		model.addAttribute("paginationInfo", paginationInfo);
		model.addAttribute("mjonCandidateTWVO", mjonCandidateTWVO);
		
		//전체 남은 리스트 수 및 전송완료 등 건수 정보 조회
		MjonCandidateTWVO resultTotCallToInfo = mjonCandidateService.selectMsgTWCallToTotCount(mjonCandidateTWVO);
		
		model.addAttribute("resultTotCallToInfo", resultTotCallToInfo);
		
		return "web/msgcampain/tw/MsgTWDataCallToListView";
	}
	
	
	@RequestMapping(value="/web/mjon/msgcampain/insertMyAddrTWCallToAjax.do")
	public ModelAndView insertMyAddrTWCallToAjax(MjonCandidateTWVO mjonCandidateTWVO) throws Exception{
		
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName("jsonView");
		
		//로그인 권한정보 불러오기
    	LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
    	String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());

    	if(userId.equals("")) {
    		
    		modelAndView.addObject("result", "loginFail");
    		modelAndView.addObject("message", "로그인이 필요합니다.");
    		return modelAndView;
    		
    	}
    	try {
			
    		List<String> callToList = new ArrayList<String>();
    		int totRowDataCnt = 0;
    		
    		for(String callTo : mjonCandidateTWVO.getCallToArr()) {
    			
    			System.out.println("++++++++++++++ callTo ::: "+callTo);
    			callToList.add(callTo);
    			totRowDataCnt++;
    			
    		}
    		
    		//수신자 목록 중복 체크 및 디비화 처리
    		List<String> dupCallToList = MJUtil.getDuplicateList(callToList);
    		
    		String dupCallCnt = Integer.toString(totRowDataCnt - dupCallToList.size());
    		
    		//입력되어있는 데이터의 마지막 순번(call_seq)을 조회해 온다.
    		int maxCallSeq = mjonCandidateService.selectCandidateTWMaxCallSeq(userId);
    		maxCallSeq += 1;//마지막 순번에 1을 더해서 다음 순번을 지정해준다.
    		
    		List<MjonCandidateTWVO> mjonCandidateTwVO = new ArrayList<MjonCandidateTWVO>();
    		
    		for(String callTo : dupCallToList) {
    			
    			MjonCandidateTWVO tmpCandidateTwVO = new MjonCandidateTWVO();
    			
    			tmpCandidateTwVO.setMberId(userId);
    			tmpCandidateTwVO.setCallTo(callTo);
    			tmpCandidateTwVO.setFrstRegisterId(userId);
    			tmpCandidateTwVO.setLastUpdusrId(userId);
    			tmpCandidateTwVO.setCallSeq(maxCallSeq);
    			
    			mjonCandidateTwVO.add(tmpCandidateTwVO);
    			
    		}
    		
    		int resultCnt = mjonCandidateService.insertCandidateTWCallToData(mjonCandidateTwVO);
    		
    		if(resultCnt > 0) {
    			
    			modelAndView.addObject("result", "success");
    			modelAndView.addObject("dupCallCnt", dupCallCnt);
    			modelAndView.addObject("maxCallSeq", maxCallSeq);
    			
    		}else {
    			
    			modelAndView.addObject("result", "fail");
        		modelAndView.addObject("message", "주소록을 불러오는 중 오류가 발생하였습니다. 잠시 후 다시 시도해 주세요.");
    			
    		}
    		
    		
		} catch (Exception e) {
			System.out.println("insertMyAddrTWCallToAjax Controller Error!!! " + e);
			modelAndView.addObject("result", "fail");
    		modelAndView.addObject("message", "주소록을 불러오는 중 오류가 발생하였습니다. 잠시 후 다시 시도해 주세요.");
    		return modelAndView;
		}
		
		return modelAndView;
	}
	
	/*
	 * 받는사람 목록 데이터 전체 초기화 처리
	 * 데이터베이스에 저장된 해당 회원의 발신목록 정보를 모두 초기화 처리
	 * */
	@RequestMapping(value="/web/mjon/msgcampain/updateMsgTWCallToListResetAjax.do")
	public ModelAndView updateMsgTWCallToListResetAjax(MjonCandidateTWVO mjonCandidateTWVO) throws Exception{
		
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName("jsonView");
		
		//로그인 권한정보 불러오기
    	LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
    	String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());

    	if(userId.equals("")) {
    		
    		modelAndView.addObject("result", "loginFail");
    		modelAndView.addObject("message", "로그인이 필요합니다.");
    		return modelAndView;
    		
    	}
    	
    	try {
    		
    		mjonCandidateTWVO.setMberId(userId);
    		
    		//수신목록 테이블에 있는 회원의 데이터를 모두 취소 처리해준다.
    		int resultCnt = mjonCandidateService.updateCandidateTWCallToDataCancel(userId);
    		
    		if(resultCnt > 0) {
    			
    			modelAndView.addObject("result", "success");
    			
    		}else {
    			
    			modelAndView.addObject("result", "fail");
        		modelAndView.addObject("message", "받는사람 초기화 중 오류가 발생하였습니다. 잠시 후 다시 시도해 주세요.");
    			
    		}
			
		} catch (Exception e) {
			System.out.println("updateMsgTWCallToListResetAjax Controller Error!!! " + e);
			modelAndView.addObject("result", "fail");
    		modelAndView.addObject("message", "받는사람 초기화 중 오류가 발생하였습니다. 잠시 후 다시 시도해 주세요.");
    		return modelAndView;
		}
		
		return modelAndView;
	}
	
	/*
	 * 받는사람 목록 선택 삭제 데이터 취소 처리
	 * 
	 * */
	@RequestMapping(value="/web/mjon/msgcampain/updateMsgTWCallToListChkDelAjax.do")
	public ModelAndView updateMsgTWCallToListChkDelAjax(MjonCandidateTWVO mjonCandidateTWVO) throws Exception{
		
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName("jsonView");
		
		//로그인 권한정보 불러오기
    	LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
    	String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());

    	if(userId.equals("")) {
    		
    		modelAndView.addObject("result", "loginFail");
    		modelAndView.addObject("message", "로그인이 필요합니다.");
    		return modelAndView;
    		
    	}
    	
    	try {
    		
    		mjonCandidateTWVO.setMberId(userId);
    		
    		int resultCnt = mjonCandidateService.updateMsgTWCallToListChkDel(mjonCandidateTWVO);
    		
    		if(resultCnt > 0) {
    			
    			modelAndView.addObject("result", "success");
    			
    		}else {
    			
    			modelAndView.addObject("result", "fail");
        		modelAndView.addObject("message", "받는사람 삭제 중 오류가 발생하였습니다. 잠시 후 다시 시도해 주세요.");
    			
    		}
			
		} catch (Exception e) {
			System.out.println("updateMsgTWCallToListResetAjax Controller Error!!! " + e);
			modelAndView.addObject("result", "fail");
    		modelAndView.addObject("message", "받는사람 초기화 중 오류가 발생하였습니다. 잠시 후 다시 시도해 주세요.");
    		return modelAndView;
		}
		
		return modelAndView;
	}
	
	@RequestMapping(value="/web/mjon/msgcampain/insertMsgTWCallToOneNumberAddAjax.do")
	public ModelAndView insertMsgTWCallToOneNumberAdd(MjonCandidateTWVO mjonCandidateTWVO) throws Exception{
		
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName("jsonView");
		
		//로그인 권한정보 불러오기
    	LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
    	String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());

    	if(userId.equals("")) {
    		
    		modelAndView.addObject("result", "loginFail");
    		modelAndView.addObject("message", "로그인이 필요합니다.");
    		return modelAndView;
    		
    	}
    	
    	try {
			
    		
    		System.out.println("================ callSeq ::: "+mjonCandidateTWVO.getCallSeq());
    		String callToNum = "";
    		for(String callTo : mjonCandidateTWVO.getCallToArr()) {
    			
    			System.out.println("++++++++++++++++ callToArr ::: "+callTo);
    			callToNum = callTo;
    			
    		}
    		
    		int callSeq = mjonCandidateTWVO.getCallSeq();
    		
    		//처음 등록되는 연락처 번호이면 기존 회원 CallSeq 마지막 번호 다음으로 신규 추가
    		if(callSeq == 0) {
    			
    			int maxCallSeq = mjonCandidateService.selectCandidateTWMaxCallSeq(userId);
    			maxCallSeq += 1;//마지막 순번에 1을 더해서 다음 순번을 지정해준다.
    			
    			mjonCandidateTWVO.setCallSeq(maxCallSeq);
    			
    		}
    		
    		//연락처 추가 관련 입력정보 셋팅해주기
    		mjonCandidateTWVO.setMberId(userId);
			mjonCandidateTWVO.setCallTo(callToNum.replaceAll("-", ""));
			mjonCandidateTWVO.setFrstRegisterId(userId);
			mjonCandidateTWVO.setLastUpdusrId(userId);
			
			//중복 연락처 체크 해주기
			int dupCallNum = mjonCandidateService.selectCandidateTWCallToDupleCnt(mjonCandidateTWVO);
			
			if(dupCallNum > 0) {
				modelAndView.addObject("result", "fail");
        		modelAndView.addObject("message", "이미 등록된 연락처 입니다. 연락처를 다시 확인해 주세요.");
				return modelAndView;
			}
			
			int resultCnt = mjonCandidateService.insertCandidateTWCallToDataOnlyAdd(mjonCandidateTWVO);
    		
			if(resultCnt > 0) {
				modelAndView.addObject("result", "success");
				modelAndView.addObject("callSeq", mjonCandidateTWVO.getCallSeq());
			}else {
				modelAndView.addObject("result", "fail");
        		modelAndView.addObject("message", "연락처 추가 중 오류가 발생하였습니다. 잠시 후 다시 시도해 주세요.");
			}
    		
    		
		} catch (Exception e) {
			System.out.println("insertMsgTWCallToOneNumberAdd Controller Error!!! " + e);
			modelAndView.addObject("result", "fail");
    		modelAndView.addObject("message", "연락처 추가 중 오류가 발생하였습니다. 잠시 후 다시 시도해 주세요.");
    		return modelAndView;
		}
    	
    	return modelAndView;
		
	}
	
	/**
	 * 선거문자 20건씩 문자 발송 - 엑셀파일 불러오기
	 * @param body
	 * @param uploadFile
	 * @param search
	 * @param result
	 * @param model
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/web/mjon/msgcampain/insertExelFileTWCallToAjax.do")
	@ResponseBody
	public Object insertExelFileTWCallToAjax(final MultipartHttpServletRequest multiRequest) throws Exception {
		
		JsonResult jr = new JsonResult();
		jr.setSuccess(false);
		jr.setMessage("엑셀 파일만 업로드할 수 있습니다.");
		
		//로그인 권한정보 불러오기
    	LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
    	String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());
    	String author = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getAuthority());
    	
    	if(userId.equals("") || author.equals("")) {
    		
    		jr.setMessage("엑셀파일 업로드는 로그인이 필요합니다.");
    		return jr;
    		
    	}
		
		try {
			
			//final Map<String, MultipartFile> files = multiRequest.getFileMap();
			List<MultipartFile> files = (List<MultipartFile>) multiRequest.getFiles("file0");
			
			// 파일명에 .이 있을경우 오류 => Ex) 테스트6.20.xlsx 
			int fileNameSplitCnt = 0;
			List<HashMap<String, String>> json = new ArrayList<HashMap<String, String>>();
			
			//전체 엑셀 데이터 갯수 체크 변수
			int totRowDataCnt = 0;
			
			//수신자 목록을 디비화 하기 위한 변수 셋팅
			List<MjonCandidateTWVO> mjonCandidateTwVO = new ArrayList<MjonCandidateTWVO>();
			List<String> callToList = new ArrayList<String>();
			
			if(!files.isEmpty()) {
				fileNameSplitCnt = files.get(0).getOriginalFilename().split("[.]").length;
				
				if (files.get(0).getSize() > 0 
						&& (files.get(0).getContentType().indexOf("spreadsheetml") > -1) 
						|| files.get(0).getContentType().indexOf("ms-excel") > -1 
						|| files.get(0).getOriginalFilename().split("[.]")[fileNameSplitCnt-1].indexOf("xlsx") > -1 
						|| files.get(0).getOriginalFilename().split("[.]")[fileNameSplitCnt-1].indexOf("xls") > -1) {
					
					// 엑셀 파일 용량 3MB이상 시 10만건 이상으로 서버가 다운되는 증상 발생
					long fileSize = multiRequest.getFile("file0").getSize();
					
					if(fileSize > 3374653) {
						jr.setMessage("엑셀 파일은 3MB를 넘을수 없습니다.");
						return jr;
					}
					
					String Ext = files.get(0).getOriginalFilename().split("[.]")[1];
					String errMessage = "";
			        String cellValue  = "";
			        
					String phoneRegExp = "^(050[234567]{1}|01[016789]{1})-?[0-9]{3,4}-?[0-9]{4}$";
					
		            int errPhoneCnt = 0;
		            String errPhoneLine = "";
		            String errEtcLine = "";
			        
		            //엑셀 확장자에 따른 처리 로직 분리
					if(Ext.equals("xls")) {
						
						HSSFWorkbook workbook = new HSSFWorkbook(files.get(0).getInputStream());
					    HSSFSheet sheet = workbook.getSheetAt(0);
					    
					    if(sheet.getLastRowNum() > 20000) { //
			            	errMessage = "20000건 이상의 업로드는 데이터 부하로 업로드 할수 없습니다.";
			            	jr.setSuccess(false);
			            	jr.setMessage(errMessage);
			            	return jr;
			            }
			            
			            //List<HashMap<String, String>> json = new ArrayList<HashMap<String, String>>();
			            PhoneVO pVO = new PhoneVO();
			            for(int i=2; i< sheet.getLastRowNum() + 2; i++){ //먼저 밸리데이션 체크(1줄은 생략)
			            	HSSFRow row = sheet.getRow(i); //열읽기
			            	if(null == row) { 
			                    continue;
			                }
			            	
			            	//전체 엑셀의 Row 갯수 카운트 해주기
			            	totRowDataCnt++;
			            	
			            	//HashMap<String, String> jm = new HashMap<>();
			            	// 행의 두번째 열(이름부터 받아오기) 
			                HSSFCell cell = null;
			                boolean errSts = true;
			                for(int j = 0 ; j < 1; j++){ //행읽기
			                	cellValue = "";
			                	cell = row.getCell(j); //핸드폰
			                	if(null == cell || "".equals(cell.toString().trim())) { //셀에 값이 없으면 
			                    	//System.out.println("Cell 데이터가 없습니다.");
			                		if(j == 0) {
				                		if (sheet.getLastRowNum() == i) {
				                			continue;
				                		}
				                		
				                		//errPhoneCnt++;
				                		//errSts = false;
				    	            	break;
			                		}
			                    	
			                    }
			                	if(null != cell){
			                		switch(cell.getCellType()){ //숫자타임을 문자로 변환
			                			case  Cell.CELL_TYPE_NUMERIC:
			                			cell.setCellType(Cell.CELL_TYPE_STRING);
			                		}
			                		cellValue =  StringUtil.getString(cell.getStringCellValue().trim()) ;
			                    }
			                	
			                	if(j == 0) {
			                		//전화번호
			                		if(cellValue.matches(phoneRegExp) && errSts) {
			                			//수신자목록을 디비화 하기 위하여 리스트에 저장해줌
			                			callToList.add(cellValue);
			                		}else {
				    	            	errPhoneCnt++;
				    	            	errPhoneLine += (i+1) + "행 ";
				    	            	errSts = false;
				    	            	break;
			                		}
			                	}
			                	
			                }
			                
			            }
			            
			            int resultErrCnt = errPhoneCnt;
			            
						if(resultErrCnt > 0) {
							if (errPhoneCnt <= 10) {
								if (StringUtils.isNotEmpty(errPhoneLine.trim())) {
									errPhoneLine = "[" + errPhoneLine.trim() + "]";
								}
							}
							else {
								errPhoneLine = "";
							}
							jr.setMessage("유효하지 않은 형식의 전화번호  "+ errPhoneCnt +"건" + errPhoneLine.trim() + " 있습니다.\n해당 건을 제외하고 수신목록에 추가됩니다.");
						}else {
							jr.setMessage("");
						}
						
					}else {	//확장자가 xlsx
						
						OPCPackage opcPackage = OPCPackage.open(files.get(0).getInputStream());
						XSSFWorkbook workbook = new XSSFWorkbook(opcPackage);
			            XSSFSheet sheet = workbook.getSheetAt(0); // 첫번째 시트 불러오기
			            opcPackage.close();
			            
			            for(int r=2; r<sheet.getPhysicalNumberOfRows(); r++) {
			            	
			            	XSSFRow tmpRow = sheet.getRow(r);
			            	//System.out.println("=================r:"+r);
			            	XSSFCell cell = null;
			            	if(tmpRow.getCell(0) != null) {
			            		
			            		cell = tmpRow.getCell(0); //핸드폰 번호만 받아오기
				            	if(cell != null && !cell.toString().trim().equals("")) {
				            		//System.out.println("value-" + r + ":" +cell.getStringCellValue()); 
				            		totRowDataCnt++;
				            		//System.out.println("tmpRowCnt:"+totRowDataCnt);
				            	}
			            		
			            	}
			            	
			            }
			            
			            //if(sheet.getLastRowNum() > 20000) { //
			            if(totRowDataCnt > 20000) { //
			            	errMessage = "20000건 이상의 업로드는 데이터 부하로 업로드 할수 없습니다.";
			            	jr.setSuccess(false);
			            	jr.setMessage(errMessage);
			            	return jr;
			            }
			            
			            //List<HashMap<String, String>> json = new ArrayList<HashMap<String, String>>();
			            PhoneVO pVO = new PhoneVO();
			            for(int i=2; i< sheet.getLastRowNum() + 2; i++){ //먼저 밸리데이션 체크(1줄은 생략)
			            	XSSFRow row = sheet.getRow(i); //열읽기
			            	if(null == row) { 
			                    continue;
			                }
			            	
			            	//HashMap<String, String> jm = new HashMap<>();
			            	// 행의 두번째 열(이름부터 받아오기) 
			                XSSFCell cell = null;
			                boolean errSts = true;
			                
			                for(int j = 0 ; j < 1; j++){ //행읽기
			                	cellValue = "";
			                	cell = row.getCell(j); //이름/핸드폰/변환1/변환2/변환3/변환4/변환5
			                	if(null == cell || "".equals(cell.toString().trim())) { //셀에 값이 없으면 
			                    	//System.out.println("Cell 데이터가 없습니다.");
			                		if(j == 0) {
				                		if (sheet.getLastRowNum() == i) {
				                			continue;
				                		}
				                		
				                		//errPhoneCnt++;
				                		//errSts = false;
				    	            	break;
				                		
			                		}
			                    }
			                	if(null != cell){
			                		switch(cell.getCellType()){ //숫자타임을 문자로 변환
			                			case  Cell.CELL_TYPE_NUMERIC:
			                			cell.setCellType(Cell.CELL_TYPE_STRING);
			                		}
			                		cellValue =  StringUtil.getString(cell.getStringCellValue().trim()) ;
			                    }
			                	
			                	if(j == 0) {
			                		//전화번호
			                		if(cellValue.matches(phoneRegExp) && errSts) {
			                			//수신자목록을 디비화 하기 위하여 리스트에 저장해줌
			                			callToList.add(cellValue);
			                			
			                		}else {
				    	            	errPhoneCnt++;
				    	            	errPhoneLine += (i+1) + "행 ";
				    	            	errSts = false;
				    	            	break;
			                		}
			                	}
			                	
			                }
			                
			            }
			            
			            int resultErrCnt = errPhoneCnt;
			            
						if(resultErrCnt > 0) {
							if (errPhoneCnt <= 10) {
								if (StringUtils.isNotEmpty(errPhoneLine.trim())) {
									errPhoneLine = "[" + errPhoneLine.trim() + "]";
								}
							}
							else {
								errPhoneLine = "";
							}
							jr.setMessage("유효하지 않은 형식의 전화번호  "+ errPhoneCnt +"건" + errPhoneLine.trim() + " 있습니다.\n해당 건을 제외하고 수신목록에 추가됩니다.");
						}else {
							jr.setMessage("");
						}
					}	//xlsx 처리 끝
					
				}
				
				//수신자 목록 중복 체크 및 디비화 처리
				List<String> dupCallToList = MJUtil.getDuplicateList(callToList);
				
				String dupCallCnt = Integer.toString(totRowDataCnt - dupCallToList.size());
				
				//입력되어있는 데이터의 마지막 순번(call_seq)을 조회해 온다.
				int maxCallSeq = mjonCandidateService.selectCandidateTWMaxCallSeq(userId);
				maxCallSeq += 1;//마지막 순번에 1을 더해서 다음 순번을 지정해준다.
				HashMap<String, String> callHm = new HashMap<>();
				for(String callTo : dupCallToList) {
					
					MjonCandidateTWVO tmpCandidateTwVO = new MjonCandidateTWVO();
					
					tmpCandidateTwVO.setMberId(userId);
					tmpCandidateTwVO.setCallTo(callTo.replaceAll("-", ""));
					tmpCandidateTwVO.setFrstRegisterId(userId);
					tmpCandidateTwVO.setLastUpdusrId(userId);
					tmpCandidateTwVO.setCallSeq(maxCallSeq);
					
					mjonCandidateTwVO.add(tmpCandidateTwVO);
					
				}
				
				int resultCnt = mjonCandidateService.insertCandidateTWCallToData(mjonCandidateTwVO);
				
				if(resultCnt > 0) {
					
					callHm.put("callSeq", Integer.toString(maxCallSeq));
					json.add(callHm);

					jr.setData(json);
					jr.setSuccess(true);
					
				}else {
					
					jr.setSuccess(false);
					jr.setMessage("엑셀 데이터 처리에 오류가 발생하였습니다. 잠시후 다시 시도해 주세요.");
					
				}
				
			}
			
			return jr;
			
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("+++++++++++++++++ insertExelFileTWCallToAjax Controller Error !!! "+e);
			jr.setSuccess(false);
			jr.setMessage("엑셀 데이터에 오류가 있습니다. 엑셀 데이터를 확인해 주세요.");
			return jr;
		}
		
	}
	
	
	/**
	 * 선거문자 20건씩 문자 발송 - TXT파일 불러오기
	 * @param body
	 * @param uploadFile
	 * @param search
	 * @param result
	 * @param model
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/web/mjon/msgcampain/insertTxtFileTWCallToAjax.do")
	@ResponseBody
	public Object insertTxtFileTWCallToAjax(final MultipartHttpServletRequest multiRequest) throws Exception {
		
		JsonResult jr = new JsonResult();
		jr.setSuccess(false);
		jr.setMessage("TXT 파일만 업로드할 수 있습니다.");
		
		//로그인 권한정보 불러오기
    	LoginVO loginVO = EgovUserDetailsHelper.isAuthenticated()? (LoginVO)EgovUserDetailsHelper.getAuthenticatedUser():null;
    	String userId = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getId());
    	String author = loginVO == null ? "" : EgovStringUtil.isNullToString(loginVO.getAuthority());
    	
    	if(userId.equals("") || author.equals("")) {
    		
    		jr.setMessage("TXT 파일 업로드는 로그인이 필요합니다.");
    		return jr;
    		
    	}
		
		try {
			
			List<MultipartFile> files = (List<MultipartFile>) multiRequest.getFiles("file0");
			List<MjonCandidateTWVO> mjonCandidateTwVO = new ArrayList<MjonCandidateTWVO>();
			List<String> callToList = new ArrayList<String>();
			List<HashMap<String, String>> json = new ArrayList<HashMap<String, String>>();
			//전체 엑셀 데이터 갯수 체크 변수
			int totRowDataCnt = 0;
			
			if(!files.isEmpty()) {
				
				if (files.get(0).getSize() > 0 
						|| files.get(0).getOriginalFilename().split("[.]")[1].indexOf("txt") > -1) {
					
					// txt 파일 용량 3MB이상 시 10만건 이상으로 서버가 다운되는 증상 발생
					long fileSize = multiRequest.getFile("file0").getSize();
					
					if(fileSize > 3374653) {
						jr.setMessage("txt 파일은 3MB를 넘을수 없습니다.");
						return jr;
					}
					
					BufferedReader reader = new BufferedReader(new InputStreamReader(multiRequest.getFile("file0").getInputStream()));
					
					String line = null;
					String[] splitedStr = null;
					String[] tempStr = null;
					int errPhoneCnt = 0;
					
					//String phoneRegExp = "^01(?:0|1|[6-9])[.-]?(\\d{3}|\\d{4})[.-]?(\\d{4})$";
					String phoneRegExp = "^(050[234567]{1}|01[016789]{1})-?[0-9]{3,4}-?[0-9]{4}$";				
					
					//파일 읽어서 탭으로 구분해주기
					while ((line = reader.readLine()) != null) {

						HashMap<String, String> jm = new HashMap<>();
						splitedStr = null;
						tempStr = null;
						
						//txt 파일의 데이터가 탭 혹은 콤마로 구분되어 있는지 구분처리
						tempStr = line.split("\t");
						if(tempStr.length > 0) {
							
							splitedStr = tempStr;
							
						}else {
							
							splitedStr = line.split(",");
							
						}

						for (int i = 0; i < splitedStr.length; i++) {

							splitedStr[i] = splitedStr[i].trim();
							
							if(i == 0) {
								
								if(splitedStr[i].matches(phoneRegExp)) {
									//휴대폰 번호
									//jm.put("phone", splitedStr[i]);
									callToList.add(splitedStr[i]);
									totRowDataCnt++;
						
								}else {
			    	            	errPhoneCnt++;
		                		}
								
							}
							
						}
						
						/*if(jm.get("phone") != null) {
							
							json.add(jm);
							
						}*/

					} // end while
					//jr.setData(json);
					//jr.setSuccess(true);
					if(errPhoneCnt > 0) {
						
						jr.setMessage("올바르지 않은 휴대폰 번호가 "+ errPhoneCnt +" 건 있습니다.");
						
					}else {
						
						jr.setMessage("");
						
					}
				}
				
				
				//수신자 목록 중복 체크 및 디비화 처리
				List<String> dupCallToList = MJUtil.getDuplicateList(callToList);
				
				String dupCallCnt = Integer.toString(totRowDataCnt - dupCallToList.size());
				
				//입력되어있는 데이터의 마지막 순번(call_seq)을 조회해 온다.
				int maxCallSeq = mjonCandidateService.selectCandidateTWMaxCallSeq(userId);
				maxCallSeq += 1;//마지막 순번에 1을 더해서 다음 순번을 지정해준다.
				HashMap<String, String> callHm = new HashMap<>();
				for(String callTo : dupCallToList) {
					
					MjonCandidateTWVO tmpCandidateTwVO = new MjonCandidateTWVO();
					
					tmpCandidateTwVO.setMberId(userId);
					tmpCandidateTwVO.setCallTo(callTo.replaceAll("-", ""));
					tmpCandidateTwVO.setFrstRegisterId(userId);
					tmpCandidateTwVO.setLastUpdusrId(userId);
					tmpCandidateTwVO.setCallSeq(maxCallSeq);
					
					mjonCandidateTwVO.add(tmpCandidateTwVO);
					
				}
				
				int resultCnt = mjonCandidateService.insertCandidateTWCallToData(mjonCandidateTwVO);
				
				if(resultCnt > 0) {
					
					callHm.put("callSeq", Integer.toString(maxCallSeq));
					json.add(callHm);

					jr.setData(json);
					jr.setSuccess(true);
					
				}else {
					
					jr.setSuccess(false);
					jr.setMessage("엑셀 데이터 처리에 오류가 발생하였습니다. 잠시후 다시 시도해 주세요.");
					
				}
				
				
			}
			
			return jr;
			
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("+++++++++++++++++ insertTxtFileTWCallToAjax Controller Error !!! "+e);
			jr.setSuccess(false);
			jr.setMessage("TXT 데이터에 오류가 있습니다. TXT 데이터를 확인해 주세요.");
			return jr;
		}
		
	}
	
}
