export class BarrageMgr {
    private static _inst: BarrageMgr = null
    public static get inst() {
        if (!this._inst)
            this._inst = new BarrageMgr();
        return this._inst;
    }

    private itemList: BarrageItem[] = [];
    private rootCanvas: mw.Canvas;
    private baseSpeed: number = 200;
    private moveVec: Vector2 = Vector.zero;
    private canvasSize: Vector2 = new Vector2(1920, 1080);
    private moveNum: number = 0;
    private winSizeX: number = 1920;
    private resetPx: number = -3000;
    private posList: number[] = [];
    private posIdx: number = 0;
    public init() {
        if (this.rootCanvas)
            return;
        let winSize = WindowUtil.getViewportSize();
        this.winSizeX = winSize.x;
        this.canvasSize.x = winSize.x;
        this.canvasSize.y = winSize.y;
        this.rootCanvas = mw.Canvas.newObject(UIService.canvas, 'Barrage');
        this.rootCanvas.visibility = mw.SlateVisibility.SelfHitTestInvisible;
        this.rootCanvas.size = this.canvasSize;
        this.rootCanvas.position = Vector2.zero;
        let max = 12;
        for (let i = 2; i < max; i++) {
            this.posList.push(i);
        }
        for (let i = 0; i < Math.ceil(max * 0.5); i++) {
            let r = MathUtil.randomInt(0, this.posList.length);
            let p = this.posList[r];
            this.posList.splice(r, 1);
            this.posList.push(p);
        }
    }
    /**
     * 显示弹幕
     * @param item 
     */
    public async showBarrage(name: string, msg: string, type: number = 0) {
        this.init();
        const item = this.getItem();
        let sx = item.setInfo(name, msg, type);
        let px = this.winSizeX + Math.abs(this.moveVec.x);
        let py = this.posList[this.posIdx];
        let ry = MathUtil.randomInt(40, 50);
        item.setPos(px, py * ry);
        this.canvasSize.x = sx;
        this.rootCanvas.size = this.canvasSize;
        this.moveNum++;
        this.posIdx++;
        if (this.posIdx >= this.posList.length)
            this.posIdx = 0;
    }
    public updateC(dt: number) {
        if (this.moveNum < 1)
            return;
        this.moveVec.x -= dt * this.baseSpeed;
        if (this.moveVec.x < this.resetPx) {
            this.moveVec.x -= this.resetPx;
            for (const item of this.itemList) {
                item.addPos(this.resetPx);
            }
        }
        this.rootCanvas.position = this.moveVec;
        //暂无速度差别
        // for (const item of this.itemList) {
        //     item.update(dt, this.baseSpeed);
        // }
    }
    private getItem() {
        for (const item of this.itemList) {
            if (item.isActive)
                continue;
            return item
        }
        let item = new BarrageItem(this.rootCanvas, this.winSizeX, this.onOut);
        this.itemList.push(item)
        return item;
    }
    private onOut = (item: BarrageItem) => {
        this.moveNum--;
        if (this.moveNum <= 0) {
            this.moveVec.x = 0;
            this.canvasSize.x = this.winSizeX;
            this.rootCanvas.position = this.moveVec;
            this.rootCanvas.size = this.canvasSize;
        }
    }
}


class BarrageItem {
    public isActive: boolean = true;
    private imgBg: mw.Image;
    private txtContent: mw.TextBlock;
    private onOut: Function;
    private size: Vector2 = new Vector2(200, 60);
    private speed: number = 200;
    private pos: Vector2 = Vector2.zero;
    private winSizeX: number = 1920;
    constructor(root: Canvas, winx: number, call: Function) {
        this.imgBg = mw.Image.newObject(root, 'BarrageItem');
        this.imgBg.imageColor = new mw.LinearColor(1, 0.6, 0.8, 0.8);
        this.imgBg.imageGuid = '163383';
        this.imgBg.imageDrawType = mw.SlateBrushDrawType.Box;
        this.imgBg.margin = new mw.Margin(0.2);

        this.txtContent = mw.TextBlock.newObject();
        this.txtContent.fontSize = 24;
        // this.txtContent.maxSize = 24;
        // this.txtContent.autoSizeHorizontalEnable = false;
        // this.txtContent.autoSizeVerticalEnable = false;
        this.txtContent.autoAdjust = false;
        this.txtContent.fontColor = mw.LinearColor.white;
        this.txtContent.position = new mw.Vector2(50, 0);
        this.txtContent.textAlign = mw.TextJustify.Left;
        this.txtContent.textVerticalAlign = mw.TextVerticalJustify.Center;
        this.imgBg.addChild(this.txtContent);
        this.onOut = call;
        this.winSizeX = winx;
        this.imgBg.visibility = mw.SlateVisibility.Collapsed;
    }
    public setInfo(name: string, msg: string, type: number) {
        let txt = StringUtil.format(`{0}: {1}`, name, msg);
        let len = this.getStrLen(txt);
        this.size.y = 66;
        this.size.x = len * 17;
        this.txtContent.size = this.size;
        this.txtContent.text = txt;
        // await TimeUtil.delaySecond(1);
        // this.size = this.txtContent.size;
        // if (this.size.x < len * 20) {
        //     this.size.x = len * 20;
        // }
        this.size.x += 66;
        this.imgBg.size = this.size;
        let dis = this.size.x + this.winSizeX;
        let dt = dis / this.speed + 1;
        this.imgBg.visibility = mw.SlateVisibility.Visible;
        this.isActive = true;
        this.setType(type);
        setTimeout(() => {
            this.hide();
        }, dt * 1000);
        return dis;
    }
    public setPos(px: number, py: number) {
        this.pos.x = px;
        this.pos.y = py;
        this.imgBg.position = this.pos;
    }
    public addPos(px: number) {
        if (!this.isActive)
            return;
        this.pos.x += px;
        this.imgBg.position = this.pos;
    }
    // public update(dt: number, bp: number) {
    //     if (!this.isActive)
    //         return;
    //     if (this.speed == bp)
    //         return;
    //     this.pos.x -= dt * this.speed;
    //     this.imgBg.position = this.pos;
    // }
    private hide() {
        this.imgBg.visibility = mw.SlateVisibility.Collapsed;
        this.isActive = false;
        this.onOut && this.onOut(this);
    }
    private icon: mw.Image;
    private setType(type: number) {
        if (!type) {
            if (this.icon)
                this.icon.visibility = mw.SlateVisibility.Collapsed;
            this.txtContent.outlineSize = 0;
            return;
        }
        if (!this.icon) {
            this.icon = mw.Image.newObject();
            this.imgBg.addChild(this.icon);
            this.icon.size = new Vector2(80, 80);
            this.icon.position = new Vector2(-40, -7);

        }
        switch (type) {
            case 1:
                this.icon.imageGuid = '115529';
                this.txtContent.outlineColor = new LinearColor(0.8, 0.45, 0.3);
                this.txtContent.outlineSize = 2;
                break;
            case 2:
                this.icon.imageGuid = '312506';
                this.txtContent.outlineColor = new LinearColor(1, 0, 0.5);
                this.txtContent.outlineSize = 2;
                break;
        }
    }
    //获取字符串的长度
    public getStrLen(str: string): number {
		let num = 0;
		for (let i = 0; i < str.length; i++) {
			let txt = str[i];
			if (/[\u4e00-\u9fa5]/.test(txt)) {
				num += 2; //汉字
			}
			else if (/[A-Z]/.test(txt)) {
				num += 1;
				if (txt == 'M' || txt == 'W')
					num += 0.45;
				else if (txt == 'G' || txt == 'O')
					num += 0.2;
				else if (txt == 'I')
					num -= 0.5;
			}
			else if (txt == ' ')
				num += 0.6;
			else {
				num++; //其他字符
				let st = txt.toLowerCase();
				if (st == 'm' || st == 'w')
					num += 0.4;
				else if (st == 'i' || txt == 'l' || txt == 'j' || txt == 'r' || txt == 'f')
					num -= 0.5;
			}
		}
		return num;
	}
}