import moment = require('moment');
import { REFRESH_TIME, TIME_OUTPUT_TYPE, SHOP_REFRESH_TYPE } from '../consts';
import { isDebugTime } from './sdkUtil';

export const WEEK_TO_MS = 7 * 24 * 60 * 60 * 1000;
export const WEEK_TO_SECOND = 7 * 24 * 60 * 60;
export const DAY_TO_HOUR = 24;
export const DAY_TO_SECOND = 24 * 60 * 60;
export const DAY_TO_MS = 24 * 60 * 60 * 1000;
export const HOUR_TO_MINUTE = 60;
export const HOUR_TO_SECOND = 60 * 60;
export const HOUR_TO_MS = 60 * 60 * 1000;
export const MINUTE_TO_MS = 60 * 1000;
export const SECOND_TO_MS = 1000;

/**
 * 时间
 * @class
 */
class Time {
    now: Date;              // 当前时间
    time: Date;             // 处理时间原料
    outputType: number;     // 输出格式

    /**
     * 
     * @param {number} outputType 输出格式 1-Date 2-10位时间戳 3-13位时间戳
     * @param {Date|number} time 传入的时间，如果不传默认为现在，可以传Date或10位或13位时间戳
     */
    constructor(outputType: TIME_OUTPUT_TYPE, time?: Date|number) {
        this.outputType = outputType;
        this.now = new Date();
        if(time) {
            if(typeof time == 'number') {
                if(time.toString().length == 10) {
                    this.time = new Date(time * 1000);
                } else {
                    this.time = new Date(time);
                }
            } else if (time instanceof Date) {
                this.time = time;
            }
        } else {
            this.time = new Date();
        }
    }

    /**
     * @description 将得出的时间按输出格式转换
     * @param time {Date|number} 时间结果
     */
    private _returnResult(time: Date| number) {
        if(this.outputType == 1) {
            if(typeof time == 'number') {
                if(time.toString().length == 10) {
                    return new Date(time * 1000);
                } else if (time.toString().length == 13) {
                    return new Date(time);
                }
            } else if (time instanceof Date) {
                return time;
            }
        } else if (this.outputType == 2) {
            if(typeof time == 'number') {
                if(time.toString().length == 10) {
                    return time;
                } else if (time.toString().length == 13) {
                    return Math.floor(time / 1000);
                }
            } else if (time instanceof Date) {
                return Math.floor(time.getTime() / 1000);
            }
        } else if (this.outputType == 3) {
            if(typeof time == 'number') {
                if(time.toString().length == 10) {
                    return time * 1000;
                } else if (time.toString().length == 13) {
                    return time;
                }
            } else if (time instanceof Date) {
                return time.getTime();
            }
        }
    }

    /**
     * @description 设置时间
     * @param time 设置的时间
     * @param hour 几点
     * @param minute 几分
     * @param seconds 几秒
     */
    private _setHour(time: number, hour: number, minute = 0, seconds = 0, millionseconds = 0) {
        let t = new Date(time);
        t.setHours(hour, minute, seconds, millionseconds);
        return t;
    }

    /**
     * @description 获得一天的刷新时间，如果是5点刷新，4点进入的话算前一天
     * @param time 设置的时间
     * @param hour 几点
     * @param minute 几分
     * @param seconds 几秒
     */
    private _getDayZeroPoint(time: Date, hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let t = this._setHour(time.getTime(), hour, minute, seconds);
        if(time >= t) {
            return t;
        } else {
            return new Date(t.getTime() - DAY_TO_MS);
        }
    }

    /**
     * 获取一周的某个时间
     * @param time 设置的时间
     * @param day 周几 周日为0
     * @param hour 几点，默认为刷新时间
     * @param minute 几分
     * @param seconds 几秒
     */
    private _getTimeWithWeek(time: Date, day: number, hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let dayOfWeek = time.getDay();
        if(dayOfWeek == 0) dayOfWeek = 7;
    
        let d = time.getDate();
        let y = time.getFullYear(); //当前年
        let m = time.getMonth(); //月
        let t = new Date(y, m, d - dayOfWeek + day, hour, minute, seconds);
        return t;
    }

    /**
     * @description 获取一月的某个时间
     * @param time 设置的时间
     * @param day 几号
     * @param hour 几点，默认为刷新时间
     * @param minute 几分
     * @param seconds 几秒
     */
    private _getTimeWithMonth(time: Date, day: number, hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let y = time.getFullYear(); //当前年
        let m = time.getMonth(); //月
        let t = new Date(y, m, day, hour, minute, seconds);
        return t;
    }

    /**
     * @description 计算某个月有几天
     * @param year 年份
     * @param month 月份，0-11，1月为0
     */
    private _countDaysInYearMonth(year: number, month: number){
        var date = new Date(year, month, 0);
        return date.getDate();
    }

    /**
     * @description 获取几个月前的某一天
     * @param time 设置的时间
     * @param month 几个月前
     * @param day 几号
     * @param hour 几点，默认为刷新时间
     * @param minute 几分
     * @param seconds 几秒
     */
    private _getBeforeMonthWithDay(time: Date, month: number, day: number, hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let y = time.getFullYear(); //当前年
        let m = time.getMonth(); //月
        if(m - month < 0) {
            m = m - month + 12;
            y --;
        } else {
            m -= month;
        }
        let days = this._countDaysInYearMonth(y, m);
        if(day > days) day = days;
        let t = new Date(y, m, day, hour, minute, seconds);
        return t;
    }

    /**
     * @description 获取两个日期之间差几天
     * @param preDate 前一天
     * @param curDate 后一天
     */
    private _getDayGap(preDate: Date, curDate: Date) {
        let cur = this._getDayZeroPoint(curDate);
        let pre = this._getDayZeroPoint(preDate);

        return Math.floor((cur.getTime() - pre.getTime()) / DAY_TO_MS)
    }

    /**
     * @description 直接获取时间
     */
    public getTime() {
        return this._returnResult(this.time);
    }

    /**
     * @description 返回某填的指定时分秒
     * @param hour 几点
     * @param minute 几分
     * @param seconds 几秒
     */
    public getTimeWithHour(hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let t = this._setHour(this.time.getTime(), hour, minute, seconds);
        return this._returnResult(t);
    }

    /**
     * 获取一周的某个时间
     * @param time 设置的时间
     * @param day 周几 周日为0
     * @param hour 几点，默认为刷新时间
     * @param minute 几分
     * @param seconds 几秒
     */
    public getTimeWithWeek(day: number, hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let t = this._getTimeWithWeek(this.time, day, hour, minute, seconds);
        return this._returnResult(t);
    }

    /**
     * 获取这个月的某个时间
     * @param day 几号
     * @param hour 几点，默认为刷新时间
     * @param minute 几分
     * @param seconds 几秒
     */
    public getTimeWithMonth(day: number, hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let t = this._getTimeWithMonth(this.time, day, hour, minute, seconds);
        return this._returnResult(t);
    }

    /**
     * @description 获得一天的刷新时间，如果是5点刷新，4点进入的话算前一天
     * @param hour 几点，默认为刷新时间
     * @param minute 几分
     * @param seconds 几秒
     */
    public getDayZeroPoint(hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let t = this._getDayZeroPoint(this.time, hour, minute, seconds);
        return this._returnResult(t);
    }

    /**
     * @description 获得一周的刷新时间，如果是5点刷新，4点进入的话算前一周
     * @param day 星期几
     * @param hour 几点，默认为刷新时间
     * @param minute 几分
     * @param seconds 几秒
     */
    public getWeekZeroPoint(day: number = 1, hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let t = this._getTimeWithWeek(this.time, day, hour, minute, seconds);
        if(this.time >= t) {
            return this._returnResult(t);
        } else {
            return this._returnResult(t.getTime() - WEEK_TO_MS);
        }
    }

    /**
     * @description 获得一个月的刷新时间，如果是5点刷新，4点进入的话算前一月
     * @param day 几号
     * @param hour 几点，默认为刷新时间
     * @param minute 几分
     * @param seconds 几秒
     */
    public getMonthZeroPoint(day: number = 1, hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let t = this._getTimeWithMonth(this.time, day, hour, minute, seconds);
        if(this.time >= t) {
            return this._returnResult(t);
        } else {
            let tt = this._getBeforeMonthWithDay(this.time, 1, day, hour, minute, seconds);
            return this._returnResult(tt);
        }
    }

    /**
     * @description 获取几天前的指定时分秒
     * @param day 几天前，（如果是输入3号3点，5点刷新，1天前指1号5点）
     * @param hour 几点，默认为刷新时间
     * @param minute 几分
     * @param seconds 几秒
     */
    public getBeforeDayWithHour(day: number = 0, hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let t = this._setHour(this.time.getTime(), hour, minute, seconds);
        if(this.time >= t) {
            let timestamp = t.getTime() - day * DAY_TO_MS;
            return this._returnResult(timestamp);
        } else {
            let timestamp = t.getTime() - (day + 1) * DAY_TO_MS;
            return this._returnResult(timestamp);
        }
    }

    /**
     * @description 获取几天后的指定时分秒，如果是指定5点刷新，6点进入的话算后一天
     * @param day 几天后，（如果是输入3号6点，5点刷新，1天后指5号5点）
     * @param hour 几点，默认为刷新时间
     * @param minute 几分
     * @param seconds 几秒
     */
    public getAfterDayWithHour(day: number = 0, hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let t = this._setHour(this.time.getTime(), hour, minute, seconds, 0);
        // console.log(t.getTime(), this.time.getTime());
        if(this.time.getTime() > t.getTime()) {
            let timestamp = t.getTime() + (day + 1) * DAY_TO_MS;
            return this._returnResult(timestamp);
        } else {
            let timestamp = t.getTime() + day * DAY_TO_MS;
            return this._returnResult(timestamp);
        }
    }

    /**
     * @description 获取几天前的指定时分秒，但是不做前后的计算
     * @param day 几天前
     * @param hour 几点，默认为刷新时间
     * @param minute 几分
     * @param seconds 几秒
     */
     public getBeforeDayAndSetHour(day: number = 0, hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let t = this._setHour(this.time.getTime(), hour, minute, seconds);
        let timestamp = t.getTime() - day * DAY_TO_MS;
        return this._returnResult(timestamp);
    }

    /**
     * @description 获取几天后的指定时分秒，但是不做前后的计算
     * @param day 几天前
     * @param hour 几点，默认为刷新时间
     * @param minute 几分
     * @param seconds 几秒
     */
     public getAfterDayAndSetHour(day: number = 0, hour = REFRESH_TIME, minute = 0, seconds = 0) {
        let t = this._setHour(this.time.getTime(), hour, minute, seconds);
        let timestamp = t.getTime() + day * DAY_TO_MS;
        return this._returnResult(timestamp);
    }
    
    /**
     * @description 获取某个时间的纯粹的几天前
     * @param day 几天前
     */
    public getBeforeDay(day: number) {
        let timestamp = this.time.getTime() - day * DAY_TO_MS;
        return this._returnResult(timestamp);
    }

    /**
     * @description 获取某个时间的纯粹的几天前
     * @param day 几天后
     */
    public getAfterDay(day: number) {
        let timestamp = this.time.getTime() + day * DAY_TO_MS;
        return this._returnResult(timestamp);
    }

    /**
     * @description 获取某个时间的纯粹的几小时前
     * @param hour 几小时前
     */
    public getBeforeHour(hour: number) {    
        let timestamp = this.time.getTime() - hour * HOUR_TO_MS; 
        return this._returnResult(timestamp);
    }

    /**
     * @description 获取某个时间的纯粹的几分钟前
     * @param hour 几分钟前
     */
    public getBeforeMinute(minute: number) {    
        let timestamp = this.time.getTime() - minute * MINUTE_TO_MS; 
        return this._returnResult(timestamp);
    }

    /**
     * @description 获取某个时间的几秒前
     * @param seconds 几秒前
     */
    public getBeforeSeconds(seconds: number) {    
        let timestamp = this.time.getTime() - seconds; 
        return this._returnResult(timestamp);
    }

    /**
     * 获取今天距离preDate整数个day天之后的时间
     * @param preDate 前一个时间点
     * @param day 几天
     */
    public getAfterDayByGap(preDate: Date, day: number) {
        let gap = this._getDayGap(preDate, this.time);
        let n = Math.floor(gap / day);
        return this._returnResult(preDate.getTime() + n * day * DAY_TO_MS);
    }

    /**
     * 检查某个时间距离今天是否在day天以内
     * @param day day天以内
     */
    public checkDay(day: number = 1) {
        if (this.time.getTime() - this.now.getTime() <= day * DAY_TO_MS) {
            return true;
        }
        return false;
    }

}

/**
 * @description 获取时间对象，10位时间戳
 * @param time 输入时间
 */
export function getTimeFun(time?: number|Date) {
    let t = new Time(TIME_OUTPUT_TYPE.STAMP_10, time);
    return t
}

/**
 * @description 获取时间对象，13位时间戳
 * @param time 输入时间
 */
export function getTimeFunM(time?: number|Date) {
    let t = new Time(TIME_OUTPUT_TYPE.STAMP_13, time);
    return t
}

/**
 * @description 获取时间对象，Date格式
 * @param time 输入时间
 */
export function getTimeFunD(time?: number|Date) {
    let t = new Time(TIME_OUTPUT_TYPE.DATE, time);
    return t
}

/**
 * @description 将某个Date格式转换为10位时间戳
 * @param time 时间
 */
export function getSeconds(time: Date) {
    let t = new Time(TIME_OUTPUT_TYPE.STAMP_10, time);
    return <number>t.getTime();
}

/**
 * @description 获取现在的10位时间戳时间
 */
export function nowSeconds() {
    let t = new Time(TIME_OUTPUT_TYPE.STAMP_10);
    return <number>t.getTime();
}

/**
 * 获取刷新时间点 10位时间戳
 * @param refreshType 刷新类型，每天/每周/每月，默认每天
 */
export function getZeroPoint(refreshType: SHOP_REFRESH_TYPE = SHOP_REFRESH_TYPE.DAILY, hour = REFRESH_TIME) {
    let t = new Time(TIME_OUTPUT_TYPE.STAMP_10);
    if(refreshType == SHOP_REFRESH_TYPE.DAILY) {
        return <number>t.getDayZeroPoint(hour);
    } else if (refreshType == SHOP_REFRESH_TYPE.WEEKLY) {
        return <number>t.getWeekZeroPoint(1, hour);
    } else if (refreshType == SHOP_REFRESH_TYPE.MONTHLY) {
        return <number>t.getMonthZeroPoint(1, hour);
    } else {
        return 0
    }
}

/**
 * 获取刷新时间点 Date类型
 * @param refreshType 刷新类型，每天/每周/每月，默认每天
 */
export function getZeroPointD(refreshType: SHOP_REFRESH_TYPE = SHOP_REFRESH_TYPE.DAILY, hour = REFRESH_TIME) {
    let t = new Time(TIME_OUTPUT_TYPE.DATE);
    if(refreshType == SHOP_REFRESH_TYPE.DAILY) {
        return <Date>t.getDayZeroPoint(hour);
    } else if (refreshType == SHOP_REFRESH_TYPE.WEEKLY) {
        return <Date>t.getWeekZeroPoint(1, hour);
    } else if (refreshType == SHOP_REFRESH_TYPE.MONTHLY) {
        return <Date>t.getMonthZeroPoint(1, hour);
    }
}

export function getZeroPointOfTime(refTime: Date|number, refreshType: SHOP_REFRESH_TYPE = SHOP_REFRESH_TYPE.DAILY, hour = REFRESH_TIME) {
    let t = new Time(TIME_OUTPUT_TYPE.STAMP_10, refTime);
    if(refreshType == SHOP_REFRESH_TYPE.DAILY) {
        return <number>t.getDayZeroPoint(hour);
    } else if (refreshType == SHOP_REFRESH_TYPE.WEEKLY) {
        return <number>t.getWeekZeroPoint(1, hour);
    } else if (refreshType == SHOP_REFRESH_TYPE.MONTHLY) {
        return <number>t.getMonthZeroPoint(1, hour);
    } else {
        return 0
    }
}

export function getZeroPointOfTimeD(refTime: Date|number, refreshType: SHOP_REFRESH_TYPE = SHOP_REFRESH_TYPE.DAILY, hour = REFRESH_TIME) {
    let t = new Time(TIME_OUTPUT_TYPE.DATE, refTime);
    if(refreshType == SHOP_REFRESH_TYPE.DAILY) {
        return <Date>t.getDayZeroPoint(hour);
    } else if (refreshType == SHOP_REFRESH_TYPE.WEEKLY) {
        return <Date>t.getWeekZeroPoint(1, hour);
    } else if (refreshType == SHOP_REFRESH_TYPE.MONTHLY) {
        return <Date>t.getMonthZeroPoint(1, hour);
    }
}

/**
 * 根据 yy-dd-mm格式获取年龄
 * 
 * @param {string} birthday 
 */
export function getAge(birthday: string) {
    let d = new Date(birthday + ' 00:00:00');
    let _year = d.getFullYear();
    let _month = d.getMonth() + 1;
    let _day = d.getDate();

    let age = 0;
    let now = new Date();
    let year = now.getFullYear();
    let month = now.getMonth() + 1;
    let day = now.getDate();

    if (year >= _year && month >= _month && day >= _day) {
        age = year - _year;
    }else{
        age = year - _year - 1;
    }
    return age
}

/**
 * 获得某个时间是星期几
 * @param needHandle 是否处理周日
 * @param {Date} time 
 */

let week = undefined;

export function getCurDay(needHandle = false, time?: Date) {
    if(!time) time = new Date();
    let d = time.getDay();

    if(isDebugTime() && week != undefined) {
        d = week;
    }
    if(needHandle && d == 0) d = 7;

    return d;
}

export function setWeek(d?: number) {
    week = d;
    if(d == 7) week = 0;
}


export function getPastTime() {
    return moment('2022-01-01').unix();
}

export function getFutureTime() {
    return moment('2100-01-01').unix();
}

 
/**
 * 判断是不是今天
 * 不是标准的0点-24点，时间区间是: 今天5点-明天5点
 *
 * @export
 * @param {number} time 单位:秒
 * @return {*}  {Boolean}
 */
export function isToday(time: number): Boolean {
    // 今天5点
    const startSeconds = getSeconds(getZeroPointD());
    // 明天5点
    const endSeconds = startSeconds + DAY_TO_SECOND;
    if ((time > startSeconds) && (time < endSeconds)) {
        return true;
    }
    return false;
}