package com.its.vds.stat.server.utils;

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

public class StatisticsTime {

    private final int processingTime_BEFORE  = 0;
    //private final int processingTime_CURRENT = 1;

    /*
     * 모든 시각은 'YYYYMMDDHH24MISS' 형태로 사용한다.
     */
    private String prcsDayWeek;			/* 요일 유형 */
    private String prcsDayQuater;		/* 분기 */

    private String prcsCurrTime;		/* 20170718153504 - 현재시각 */
    private String prcsCurrFiveMin;		/* 20170718153500 - 현재 정주기 5분 시각 */
    private String prcsCurrFiveMinTo;   /* 20170718153459 - 현재 정주기 5분 시각 - 1초 */
    private String prcsPrevFiveMin;		/* 20170718153000 - 이전 정주기 5분 시각 */

    private String stat15MinTime;
    private String stat15MinFrom;
    private String stat15MinTo;
    private String statHourTime;
    private String statHourFrom;
    private String statHourTo;
    private String statDayFrom;
    private String statDayTo;
    private String statMonFrom;
    private String statMonTo;
    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 isPatternUpdate = false;

    private int analysisTime = processingTime_BEFORE;		/* 이전주기시각(0)/현재주기시각(1) */
    private int month, hour, min;

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

    public StatisticsTime() {
        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 boolean IsProcessing() { return this.isProcessing; }
    public Date    getStartDate() { return this.startDate; }
    public Date    getEndDate()   { return this.endDate; }

    public int getAnalysisTime() { return this.analysisTime; }
    public void setAnalysisTime(int analysisTime) { this.analysisTime = analysisTime; }

    public boolean isStat15Min() { return this.isStat15Min; }
    public boolean isStatHour()  { return this.isStatHour; }
    public boolean isStatDay()   { return this.isStatDay; }
    public boolean isStatMon()   { return this.isStatMon; }
    public boolean isStatYear()   { return this.isStatYear; }

    public boolean isPatternUpdate() { return this.isPatternUpdate; }

    public String getStat15MinTime() {
        if (this.analysisTime == processingTime_BEFORE)
            return this.stat15MinFrom;
        return this.stat15MinTime;
    }
    public String getStat15MinFrom() { return this.stat15MinFrom; }
    public String getStat15MinTo()   { return this.stat15MinTo; }
    public String getStatHourTime() {
        if (this.analysisTime == processingTime_BEFORE)
            return this.statHourFrom;
        return this.statHourTime;
    }
    public String getStatHourFrom()  { return this.statHourFrom; }
    public String getStatHourTo()    { return this.statHourTo; }
    public String getStatDayFrom()   { return this.statDayFrom; }
    public String getStatDayTo()     { return this.statDayTo; }
    public String getStatMonFrom()   { return this.statMonFrom; }
    public String getStatMonTo()     { return this.statMonTo; }
    public String getStatYearFrom()  { return this.statYearFrom; }
    public String getStatYearTo()    { return this.statYearTo; }

    public String getPrcsDayWeek()   { return this.prcsDayWeek; }
    public String getPrcsDayQuater() { return this.prcsDayQuater; }

    public String getCurrTime() { return this.prcsCurrTime;	 }
    public String getPrcsFiveMin() {
        /*
         * 정주기 5분 가공시각으로 DB에 저장하는 시각, 현재시각 이전정주기 5분 시각을 사용한다.
         * 만일, 현재정주기 5분 시각을 사용하려 한다면 prcsCurrFiveMin 를 사용한다.
         */
        if (this.analysisTime == processingTime_BEFORE)
            return this.prcsPrevFiveMin;

        return this.prcsCurrFiveMin;
    }

    public String getCurrFiveMin()     { return this.prcsCurrFiveMin; }
    public String getPrcsFiveMinFrom() { return this.prcsPrevFiveMin; }
    public String getPrcsFiveMinTo()   { return this.prcsCurrFiveMinTo; }

    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 = TimeUtils.dateToString(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 = TimeUtils.dateToString(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 void setPrcsTimeInfo() {
        Calendar cal = Calendar.getInstance();
        try {
            cal.setTime(TimeUtils.stringToDate(this.prcsCurrTime));
        } catch (Exception e) {
            e.printStackTrace();
        }

        /* 년월일시분초는 현재시각 기준으로 계산 */
        //this.year  = cal.get(Calendar.YEAR);
        this.month = cal.get(Calendar.MONTH) + 1;
        //this.day   = cal.get(Calendar.DAY_OF_MONTH);
        this.hour  = cal.get(Calendar.HOUR_OF_DAY);
        this.min   = cal.get(Calendar.MINUTE);
        //this.sec   = cal.get(Calendar.SECOND);

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

    public void initValue() {
        this.prcsDayWeek   = "";		/* 요일 유형 */
        this.prcsDayQuater = "";		/* 분기 */

        this.prcsCurrTime      = "";	/* 20170718153504 - 현재시각 */
        this.prcsCurrFiveMin   = "";	/* 20170718153500 - 현재 정주기 5분 시각 */
        this.prcsCurrFiveMinTo = "";    /* 20170718153459 - 현재 정주기 5분 시각 - 1초 */
        this.prcsPrevFiveMin   = "";	/* 20170718153000 - 이전 정주기 5분 시각 */

        this.stat15MinTime = "";
        this.stat15MinFrom = "";
        this.stat15MinTo   = "";
        this.statHourTime  = "";
        this.statHourFrom  = "";
        this.statHourTo    = "";
        this.statDayFrom   = "";
        this.statDayTo     = "";
        this.statMonFrom   = "";
        this.statMonTo     = "";

        this.isStat15Min = false;
        this.isStatHour  = false;
        this.isStatDay   = false;
        this.isStatMon   = false;
        this.isStatYear  = false;

        this.isPatternUpdate = false;
    }
    public void init() {

        initValue();

        /*
         * 시간대 계산은 아직 안함(추후 시간대 계산이 필요하면 여기서 하면 됨)
         */
        this.prcsCurrTime = TimeUtils.getCurrentTimeString();

        Date dt = null;
        try {
            dt = TimeUtils.stringToDate(this.prcsCurrTime);
        } catch (Exception e) {
            e.printStackTrace();
        }

        this.prcsCurrFiveMin   = TimeUtils.getFiveMinString(dt);
        this.prcsCurrFiveMinTo = calDate(this.prcsCurrFiveMin, -1);		/* 현재 정주기 시각에서 -1초 */
        this.prcsPrevFiveMin   = calDate(this.prcsCurrFiveMin, -60*5); 	/* 20170718153000 - 이전 정주기 5분 시각 */

        setPrcsTimeInfo();

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

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

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

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

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

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