import IDisplayText = eui.IDisplayText;
import { HtmlTextParser } from "../../libs/tc/util/HtmlTextParser";

/**
 * 简单的倒计时
 * Created on 2019/10/24
 */
export default class CutTimer {
    private _timer: egret.Timer = null;
    private readonly _label: IDisplayText = null;

    private _labelText: string = "hh:mm:ss";
    public set labelText(labelText: string) {
        this._labelText = labelText;
    }

    // 倒计时时间
    private _cutTime: number = 0;
    public set cutTime(cutTime: number) {
        this._cutTime = cutTime;
    }

    // 回调函数
    private _callFun: Function = null;
    public set callFun(callFun: Function) {
        this._callFun = callFun;
    }

    /**
     * @param label 传入显示的label
     * @param labelText 该字符串将作为倒计时显示的文字，hh、mm、ss将被分别替换成时，分，秒，例：将在hh:mm:ss后消失 -> 将在18:07:21后消失
     * @param callFun 如果希望他在结束时去做一些什么则传入一个回调函数
     */
    constructor(label?: IDisplayText, labelText?: string, callFun?: Function) {
        this._label = label || null;
        this._labelText = labelText || "hh:mm:ss";
        this._callFun = callFun || null;
    }

    /**
     * 根据时间开始倒计时
     * 1.假如已经存在一个倒计时返回false（失败），表示要先执行stop或stopAndCallFun
     * 2.保存倒计时时间 +1秒弥补第5步操作
     * 3.创建一个倒计时对象
     * 4.注册时间监听
     * 5.立即执行一次倒计时（为了立即刷新label）
     * 6.开始倒计时
     * 7.返回true（成功）
     * @param cutTime 时间戳
     */
    public start(cutTime: number) {
        if(this._timer) {
            return false;
        }
        this._cutTime = cutTime + 1000; // +1秒弥补立即刷新
        this._timer = new egret.Timer(1000, 0);
        this._timer.addEventListener(egret.TimerEvent.TIMER, this._cutTimer, this);
        this._cutTimer();
        this._timer.start();
        return true;
    }

    /**
     * 结束计时器，不执行回调函数
     * 1.停止计时器
     * 2.移除事件监听
     * 3.置空计时器
     * 4.如果希望执行回调函数请使用stopAndCallFun()
     */
    public stop() {
        if(!this._timer) {
            return;
        }
        this._timer.stop();
        this._timer.removeEventListener(egret.TimerEvent.TIMER, this._cutTimer, this);
        this._timer = null;
    }

    /**
     * 结束倒数计时并执行回调函数
     * 1.停止计时器
     * 2.移除事件监听
     * 3.置空计时器
     * 4.执行回调函数函数，如果不希望执行回调函数则使用stop()
     */
    public stopAndCallFun() {
        if(!this._timer) {
            return;
        }
        this._timer.stop();
        this._timer.removeEventListener(egret.TimerEvent.TIMER, this._cutTimer, this);
        this._timer = null;
        if(this._callFun) {
            this._callFun();
        }
    }

    /**
     * 倒计时回调函数
     * @private
     */
    private _cutTimer() {
        let timer = this._convertTime(this._cutTime -= 1000);
        if(timer.hour === "00"
            && timer.min === "00"
            && timer.sec === "00") {
            this.stopAndCallFun();
        }
        if(!this._label){
            return;
        }
        let str = this._labelText;
        str = str.replace(/hh/g, timer.hour);
        str = str.replace(/mm/g, timer.min);
        str = str.replace(/ss/g, timer.sec);
        if(this._label instanceof eui.Label) {
            this._label.textFlow = (new HtmlTextParser).parser(str);
        } else {
            this._label.text = str;
        }
    }

    /**
     * 通过时间戳获取几时积分几秒    例：666666666 -> {hour: 18, min: 51, sec: 16}
     * @param time 时间戳（毫秒）
     * @private
     */
    private _convertTime(time: number): { hour, min, sec } {
        let hour = ~~(time / 3600000);                              // 小时
        let min = ~~((time - hour * 3600000) / 60000);              // 分
        let sec = ~~((time - hour * 3600000 - min * 60000) / 1000); // 秒

        return {
            hour: this._prefixInteger(hour, 2),
            min: this._prefixInteger(min, 2),
            sec: this._prefixInteger(sec, 2)
        }
    }

    /**
     * 数字补0 例：(num = 2, length = 2) -> 02
     * @param num 数字
     * @param length 位数
     * @private
     */
    private _prefixInteger(num, length): string {
        return (Array(length).join('0') + num).slice(-length);
    }

}