package com.its.op.service.its;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

@Slf4j
@Getter
@Setter
@Service
public class TrafPrcsTime {

	/*
	 * 모든 시각은 'YYYYMMDDHH24MISS' 형태로 사용한다.
	 */

	/*
	 *  데이터베이스에 입력 또는 데어터 조회 하는 시각을 설정하기 위해 사용한다.
	 */
	private String currTime;			/* 20170718153504 - 현재시각 */
	private String currFiveMin;			/* 20170718153500 - 현재시각 - 초를 00으로 초기화한 현재 정주기 5분 시각 */
	private String prevFiveMin;			/* 20170718153000 - 이전 정주기 5분 시각 */
	private String prcsFiveMin;			/* 20170718153500 - 현재 정주기 5분 시각 - 시스템에 따라 5분 이전시각이 될수 있고 현재 정주기 5분 시각이 될수 있다. */
	private String prcsFiveMinFrom; 	/* 20170718153000 - 이전 정주기 5분 시각 */
	private String prcsFiveMinTo;   	/* 20170718153459 - 이전 정주기 5분 시각 + 4분 59초 */
	private String prcs10Min;

	private String prcsDayWeekCd;
	private int    prcsDayWeek;			/* 요일 유형 - prcsFiveMin */
	private String prcsDayQuater;		/* 분기 - prcsFiveMin */

	private String stat15MinTime;
	private String stat15MinFrom;
	private String stat15MinTo;

	private String statHourTime;
	private String statHourFrom;
	private String statHourTo;

	private String statDayTime;
	private String statDayFrom;
	private String statDayTo;

	private String statMonTime;
	private String statMonFrom;
	private String statMonTo;

	private String statYearTime;
	private String statYearFrom;
	private String statYearTo;

	private boolean isStat15Min = false;
	private boolean isStatHour  = false;
	private boolean isStatDay   = false;
	private boolean isStatMon   = false;
	private boolean isStatYear  = false;

	private boolean changePtrnMonth;

	private boolean isPatternUpdate = false;
	
	private boolean isProcessing = false;
	private Date    startDate;
	private Date    endDate;

	private String ptrn05M;
	private String ptrn15M;

	public TrafPrcsTime() {
		startDate = new Date();
		endDate   = new Date();
	}

	public void setProcessing(boolean isProcessing) {
		this.isProcessing = isProcessing;
		if (this.isProcessing) {
			startDate = new Date();
		}
		else {
			endDate = new Date();
		}
	}

	public Date convertString2Date(String paramTime) {
		SimpleDateFormat transFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		Date to = null;
		try {
			to = transFormat.parse(paramTime);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return to;
	}

	public String getDateToString(Date paramDt, String paramFmt) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(paramDt);
		return new SimpleDateFormat(paramFmt).format(cal.getTime());
	}
	public String getCurrFiveMinString(Date paramDt) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(paramDt);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		int min = cal.get(Calendar.MINUTE);
		cal.add(Calendar.MINUTE, -(min % 5));
		return new SimpleDateFormat("yyyyMMddHHmmss").format(cal.getTime());
	}

	public String calDate(String paramTm, int addSec/*초단위*/) {
		String result = paramTm;
		SimpleDateFormat transFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		try {
			Date to = new Date();
			addSec = addSec * 1000;	/* mili-second로 변환 */
			to.setTime(transFormat.parse(paramTm).getTime() + addSec);
			result = getDateToString(to, "yyyyMMddHHmmss");
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}

	public String calDateFormat(String paramFmt, String paramTm, int addSec) {
		String result = paramTm;
		SimpleDateFormat transFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		try {
			Date to = new Date();
			addSec = addSec * 1000;	/* mili-second로 변환 */
			to.setTime(transFormat.parse(paramTm).getTime() + addSec);
			result = getDateToString(to, paramFmt);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public String calLastDayFormat(String paramFmt, String paramTm) {
		String result = paramTm;
		SimpleDateFormat transFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		try {
			Date to = new Date();
			to.setTime(transFormat.parse(paramTm).getTime());
			Calendar cal = Calendar.getInstance();
			cal.setTime(to);
			int day = cal.getActualMaximum(Calendar.DATE);
			
			cal.set(Calendar.DAY_OF_MONTH, day);
			return new SimpleDateFormat(paramFmt).format(cal.getTime());
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public String getCurrentTimeString() {
		Calendar cal = Calendar.getInstance();
		return new SimpleDateFormat("yyyyMMddHHmmss").format(cal.getTime());
	}

	public void initValue() {
		this.currTime    = "";
		this.currFiveMin = "";
		this.prevFiveMin = "";

		this.prcsFiveMin     = "";
		this.prcsFiveMinFrom = "";
		this.prcsFiveMinTo   = "";

		this.prcsDayWeek   = 0;		/* 요일 유형 */
		this.prcsDayQuater = "";		/* 분기 */

		this.stat15MinTime = "";
		this.stat15MinFrom = "";
		this.stat15MinTo   = "";

		this.statHourTime  = "";
		this.statHourFrom  = "";
		this.statHourTo    = "";

		this.statDayTime   = "";
		this.statDayFrom   = "";
		this.statDayTo     = "";

		this.statMonTime   = "";
		this.statMonFrom   = "";
		this.statMonTo     = "";

		this.statYearTime   = "";
		this.statYearFrom   = "";
		this.statYearTo     = "";

		this.isStat15Min = false;
		this.isStatHour  = false;
		this.isStatDay   = false;
		this.isStatMon   = false;
		this.isStatYear  = false;
		
		this.isPatternUpdate = false;
	}
	public void init() {

		initValue();

		/*
		 * 시간대 계산은 아직 안함(추후 시간대 계산이 필요하면 여기서 하면 됨)
		 */
		this.currTime = getCurrentTimeString();										/* 20170718153504 - 현재시각 */
		this.currFiveMin = getCurrFiveMinString(convertString2Date(this.currTime));	/* 20170718153500 */
		this.prevFiveMin = calDate(this.currFiveMin, -60*5); 				/* 20170718153000 - 이전 정주기 5분 시각 */

		String beforeOneWeek = calDate(this.currTime, -60*60*24*7);			/* 7일전 */
		this.ptrn05M = getCurrFiveMinString(convertString2Date(beforeOneWeek));		/* 7일전 정주기 05분 패턴 시각 */
		this.ptrn15M = calDate(this.ptrn05M, -60*15);						/* 7일전 정주기 15분 패턴 시각 */

		this.prcsFiveMin     = this.prevFiveMin;									/* 20170718153000 - 이전 정주기 5분 시각 이용하여 입력 */
		this.prcsFiveMinFrom = this.prevFiveMin;									/* 20170718153000 - 이전 정주기 5분 시각 */
		this.prcsFiveMinTo   = calDate(this.currFiveMin, -1);				/* 20170718153459 - 현재 정주기 시각에서 -1초 */

		Calendar cal = Calendar.getInstance();
		cal.setTime(convertString2Date(this.currFiveMin));							/* 년월일시분초는 현재시각 기준으로 계산 */
		int year  = cal.get(Calendar.YEAR);
		int month = cal.get(Calendar.MONTH) + 1;
		int day   = cal.get(Calendar.DAY_OF_MONTH);
		int hour  = cal.get(Calendar.HOUR_OF_DAY);	// 24시간제, HOUR: 12시간제
		int min   = cal.get(Calendar.MINUTE);
		int sec   = cal.get(Calendar.SECOND);

		String strCurrTime = String.format("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, min, sec);
		log.info("[PROCESSING] TrafficProcessingTime.init: {}", strCurrTime);

		cal.setTime(convertString2Date(this.prcsFiveMin));		/* 요일, 사사분기는 가공시각을 기준으로 계산 */
		this.prcsDayWeek   = cal.get(Calendar.DAY_OF_WEEK);		/* DAY_OF_WEEK 리턴값이 일요일(1), 월요일(2), 화요일(3) ~~ 토요일(7)을 반환합니다. */
		this.prcsDayQuater = String.valueOf((month/3)+1);

		/*
		 * 5분 정주기 가공이 끝나고 15분 주기일 경우(00, 15, 30, 45 분 일경우 15분 통계 정보를 생성한다)
		 */
		if (min % 15 == 0) {
			this.isStat15Min = true;
		}
		this.prcs10Min = calDate(this.currFiveMin, -60*10);
		this.stat15MinFrom = calDate(this.currFiveMin, -60*15);
		this.stat15MinTo   = calDate(this.stat15MinFrom,   (60*15)-1);
		this.stat15MinTime = this.stat15MinFrom;

		/*
		 * 매시 5분 가공이 끝나면 1시간 통계 정보를 생성한다.
		 */
		if (min == 5) {
			this.isStatHour = true;
		}
		String statHour = calDateFormat("yyyyMMddHH", this.currFiveMin, -60*60);
		this.statHourFrom = statHour + "0000";
		this.statHourTo   = statHour + "5959";
		this.statHourTime = this.statHourFrom;

		/*
		 * 00시 10분 가공이 끝나면 이전일의 통계 정보를 가공.
		 */
		if (hour == 0 && min == 10) {
			this.isStatDay = true;
		}
		String statDay = calDateFormat("yyyyMMdd", this.currFiveMin, -60*60*24);
		this.statDayFrom = statDay + "000000";
		this.statDayTo   = statDay + "235959";
		this.statDayTime = statDay + "000000";

		/*
		 * 01시 10분 가공이 끝나면 이전일의 월통계 정보를 누적 가공.
		 */
		if (hour == 1 && min == 10) {
			this.isStatMon = true;
		}
		this.statMonFrom = calDateFormat("yyyyMM", this.currFiveMin, -60*60*24) + "01000000";
		this.statMonTo   = calLastDayFormat("yyyyMMdd", this.statMonFrom)                +   "235959";
		this.statMonTime = calDateFormat("yyyyMM", this.currFiveMin, -60*60*24) + "00000000";

		/*
		 * 02시 5분 가공이 끝나면 이전일의 연통계 정보를 누적 가공.
		 */
		if (hour == 2 && min == 10) {
			this.isStatYear = true;
		}
		this.statYearTime = calDateFormat("yyyy", this.currFiveMin, -60*60*24);
		this.statYearFrom = this.statYearTime + "0101000000";
		this.statYearTo   = this.statYearTime + "1231235959";
		this.statYearTime = this.statYearTime + "0000000000";

		/*
		 * 패턴업데이트 시각 체크: 매일 새벽 3시 10분
		 */
		if (hour == 3 && min == 10) {
			this.isPatternUpdate = true;
		}
	}

	public String getStat15M(String prcsDt) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(convertString2Date(prcsDt));
		int year  = cal.get(Calendar.YEAR);
		int month = cal.get(Calendar.MONTH) + 1;
		int day   = cal.get(Calendar.DAY_OF_MONTH);
		int hour  = cal.get(Calendar.HOUR_OF_DAY);	// 24시간제, HOUR: 12시간제
		int min = cal.get(Calendar.MINUTE);
		min = (int)(min / 15);
		min = min * 15;

		return String.format("%04d%02d%02d%02d%02d00", year, month, day, hour, min);
	}

	/* 정주기 현재 5분 시각 */
	public String getCurrentFiveMinString() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		int min = cal.get(Calendar.MINUTE);
		cal.add(Calendar.MINUTE, -(min % 5));
		return new SimpleDateFormat("yyyyMMddHHmmss").format(cal.getTime());
	}
	public String getCurrentFiveMinToString() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		int min = cal.get(Calendar.MINUTE);
		cal.add(Calendar.MINUTE, -(min % 5));
		cal.add(Calendar.SECOND, -1);	/* 정주기 현재 5분 시각에서 1초를 뺀 시각 */
		return new SimpleDateFormat("yyyyMMddHHmmss").format(cal.getTime());
	}

	/* 정주기 이전 5분 시각 */
	public String getBeforeFiveMinString() {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		int min = cal.get(Calendar.MINUTE);
		cal.add(Calendar.MINUTE, -(min % 5) - 5);	/* 정주기 현재 5분에서 5분을 뺀 시각 */
		return new SimpleDateFormat("yyyyMMddHHmmss").format(cal.getTime());
	}

	/* 현재 시각을 문자열로 리턴 */
	public String getCurrentTimeString(String parmaFmt) {
		Calendar cal = Calendar.getInstance();
		return new SimpleDateFormat(parmaFmt).format(cal.getTime());
	}
	
	/* 현재 시각을 Date 형으로 리턴 */
	public Date getCurrentDate() {
		Calendar cal = Calendar.getInstance();
		return cal.getTime();
	}

	/* 현재 시각을 second 로 리턴 */
	public long getCurrentTimeSeconds() {
		Calendar cal = Calendar.getInstance();
		return cal.getTimeInMillis();
		//return System.currentTimeMillis();
	}

	public int getDayWeek(String paramDt) {
		return getDayWeek(convertString2Date(paramDt));
	}
	public int getDayWeek(Date paramDt) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(paramDt);
		return cal.get(Calendar.DAY_OF_WEEK);		/* DAY_OF_WEEK 리턴값이 일요일(1), 월요일(2), 화요일(3) ~~ 토요일(7)을 반환합니다. */
	}
}
