import { SCALE_MODES, TEXT_ALIGN, TEXT_lINETYPE, VERTICAL_ALIGN } from "../const";
import Texture from "../texture/Texture";
import { getRGBA } from "../utils";
import { Rectangle } from "../math";
import Sprite from "../display/Sprite";

//文本canvas上xy的偏移量
const padding = 10;
/**
 * 
 * 继承Sprite，暂时发现，只需要切换bitmap和Sprite,TextField永远都是最新的，到时替换
 * 动态文本类,有时需要在canvas里有一个动态文本,能根据我们的显示内容来改变
 * @class TextFieldCon
 * @extends DisplayObject
 * @since 1.0.0
 * @public
 */
export class TextField extends Sprite {

    canvas: HTMLCanvasElement;
    context: CanvasRenderingContext2D;
    /**
     * 与其他类不同，用了Boolean，再考虑
     */
    dirty: boolean;

    offsetX: number;
    offsetY: number;
    constructor() {
        super();
        this._instanceType = "TextField";
        var canvas = document.createElement('canvas');
        canvas.width = 3;
        canvas.height = 3;
        this.texture = Texture.fromCanvas(canvas, SCALE_MODES.LINEAR, 'textCanvas');
        //baseTexture已自动缓存，把texture也缓存，key textCanvas+num  和baseTexture的一致
        Texture.addToCache(this.texture, this.texture.baseTexture.textureCacheIds[0]);
        this.canvas = canvas;
        this.context = canvas.getContext("2d");
        this.dirty = true;

    }

    /**
     * @property textAlpha
     * @since 2.0.0
     * @public
     */
    public set textAlpha(value: number) {
        if (this._textAlpha != value) {
            this._textAlpha = value;
            this.dirty = true;
        }
    }

    public get textAlpha(): number {
        return this._textAlpha;
    }
    private _textAlpha: number = 1;

    /**
     * 文本的水平对齐方式 left center right
     * 设置过textHeight才有效，如果是多行的，对排版有作用
     * @property textAlign
     * @public
     * @since 1.0.0
     * @type {string}
     * @default left
     */
    public set textAlign(value: TEXT_ALIGN) {
        if (this._textAlign != value) {
            this._textAlign = value;
            this.dirty = true;
        }
    }

    public get textAlign(): TEXT_ALIGN {
        return this._textAlign;
    }
    private _textAlign: TEXT_ALIGN = TEXT_ALIGN.LEFT;

    /**
     * 垂直对齐方式 
     * 设置过textHeight才有效
     */
    public set verticalAlign(value: VERTICAL_ALIGN) {
        if (this._verticalAlign != value) {
            this._verticalAlign = value;
            this.dirty = true;
        }
    }

    public get verticalAlign(): VERTICAL_ALIGN {
        return this._verticalAlign;
    }
    private _verticalAlign: VERTICAL_ALIGN = VERTICAL_ALIGN.UP;

    /**
     * 文本的宽，
     * @property textWidth
     * @public
     * @since 1.0.0
     * @type {number}
     * @default 0
     */
    public set textWidth(value: number) {
        if (this._textWidth != value) {
            this._textWidth = value;
            this.dirty = true;
        };
    }
    public get textWidth(): number {
        if (this._textWidth) {
            //有就这个
            return this._textWidth
        } else {
            //没有就计算出的给width，还是
            this.updateText();
            return this.width - padding * 2;
        }
    }
    private _textWidth: number = 0;

    /**
     * 文本的行高，设置过能进行垂直适配，
     * 文本超出行高会被裁切
     * @property textHeight
     * @public
     * @since 1.0.0
     * @type {number}
     * @default 0
     */
    public set textHeight(value: number) {
        if (this._textHeight != value) {
            this._textHeight = value;
            this.dirty = true;
        }
    }

    public get textHeight(): number {
        if (this._textHeight) {
            //有就这个
            return this._textHeight
        } else {
            //没有就计算出的给height，还是
            this.updateText();
            return this.height - padding * 2
        }
    }
    private _textHeight: number = 0;

    /**
     * 行间距
     * @property lineSpacing
     * @public
     * @since 1.0.0
     * @param {number} value
     */
    public set lineSpacing(value: number) {
        if (this._lineSpacing != value) {
            this._lineSpacing = value;
            this.dirty = true;
        };
    }
    public get lineSpacing(): number {
        return this._lineSpacing;
    }
    private _lineSpacing: number = 14;

    /**
     * 文本类型,单行还是多行 single multi
     * @property lineType
     * @public
     * @since 1.0.0
     * @type {string} 两种 single和multi
     * @default single
     */
    public set lineType(value: TEXT_lINETYPE) {
        if (this._lineType != value) {
            this._lineType = value;
            this.dirty = true;
        };
    }
    public get lineType(): TEXT_lINETYPE {
        return this._lineType;
    }
    private _lineType: TEXT_lINETYPE = TEXT_lINETYPE.SINGLE;
    /**
     * 文本内容
     * @property text
     * @type {string}
     * @public
     * @default ""
     * @since 1.0.0
     */
    public set text(value: string) {
        if (this._text != value) {
            this._text = value;
            this.dirty = true;
        };
    }

    public get text(): string {
        return this._text;
    }
    private _text: string = "";
    /**
     * 文本的css字体样式
     * @property font
     * @public
     * @since 1.0.0
     * @type {string}
     * @default 12px Arial
     */
    public set font(value: string) {
        if (this._font != value) {
            this._font = value;
            this.dirty = true;
        };
    }

    public get font(): string {
        return this._font;
    }
    private _font: string = "Arial";
    /**
     * 文本的size
     * @property size
     * @public
     * @since 1.0.0
     * @type {number}
     * @default 12
     */
    public set size(value: number) {
        if (this._size != value) {
            this._size = value;
            this.dirty = true;
        };
    }

    public get size(): number {
        return this._size;
    }
    private _size: number = 12;
    /**
     * 文本的填充颜色值
     * @property fillColor
     * @type {string}
     * @public
     * @since 1.0.0
     * @default #fff
     */
    public set fillColor(value: string) {
        if (this._fillColor != value) {
            this._fillColor = value;
            this.dirty = true;
        };
    }

    public get fillColor(): string {
        return this._fillColor;
    }
    private _fillColor: string = "#ffffff";

    /**
     * 文本的描边颜色值
     * @property strokeColor
     * @type {string}
     * @public
     * @since 1.0.0
     * @default #fff
     */
    public set strokeColor(value: string) {
        if (this._strokeColor != value) {
            this._strokeColor = value;
            this.dirty = true;
        };
    }

    public get strokeColor(): string {
        return this._strokeColor;
    }
    private _strokeColor: string = "#ffffff";
    /**
     * 文本描边宽度,为0则不描边
     * @property stroke
     * @public
     * @since
     * @default 0
     * @type {number}
     */
    public set stroke(value: number) {
        if (this._stroke != value) {
            this._stroke = value;
            this.dirty = true;
        };
    }

    public get stroke(): number {
        return this._stroke;
    }
    private _stroke: number = 0;

    /**
     * 文本是否倾斜
     * @property italic
     * @public
     * @since
     * @default false
     * @type {boolean}
     */
    public set italic(value: boolean) {
        if (this._italic != value) {
            this._italic = value;
            this.dirty = true;
        };
    }

    public get italic(): boolean {
        return this._italic;
    }
    private _italic: boolean = false;
    /**
     * 文本是否加粗
     * @property bold
     * @public
     * @since
     * @default false
     * @type {boolean}
     */
    public set bold(value: boolean) {
        if (this._bold != value) {
            this._bold = value;
            this.dirty = true;
        };
    }
    public get bold(): boolean {
        return this._bold;
    }
    public _bold: boolean = false;
    /**
     * 设置或获取是否有边框
     * @property property
     * @param {boolean} show true或false
     * @public
     * @since 1.0.6
     */
    public set border(value: boolean) {
        if (this._border != value) {
            this._border = value;
            this.dirty = true;
        };
    }

    public get border(): boolean {
        return this._border;
    }
    private _border: boolean = false;

    /**
     * 设置文本在canvas里的渲染样式
     * @method _prepContext
     * @param ctx
     * @private
     * @since 1.0.0
     */
    private _prepContext(ctx: CanvasRenderingContext2D): void {
        let s = this;
        let font: any = s.size || 12;
        font += "px ";
        font += s.font;
        //font-weight:bold;font-style:italic;
        if (s._bold) {
            font = "bold " + font;
        }
        if (s._italic) {
            font = "italic " + font;
        }
        ctx.font = font;
        ctx.textAlign = s._textAlign || TEXT_ALIGN.LEFT;
        //暂时没开放
        ctx.textBaseline = "top";
        ctx.fillStyle = getRGBA(s._fillColor, s._textAlpha)
    }
    /**
     * 获取当前文本中单行文字的宽，注意是文字的不是文本框的宽，貌似没啥用，基本用textWidth了
     * @method getTextWidth
     * @param {number} lineIndex 获取的哪一行的高度 默认是第1行
     * @since 2.0.0
     * @public
     * @return {number}
     */
    // public getTextWidth(lineIndex: number = 0): number {
    //     let s = this;
    //     //先更新一次文本，万一是dirty，不是dirty也不影响性能
    //     s.updateText();
    //     return s._getMeasuredWidth(s.realLines[lineIndex]);
    // }
    /**
     * @property _lines 获取当前文本行数
     * @type {number}
     * @public
     * @readonly
     * @since 2.0.0
     */
    get lines(): number {
        return this.realLines.length;
    }
    /**
     * 获取文本宽
     * @method _getMeasuredWidth
     * @param text 测量的文本内容
     * @return {number}
     * @private
     * @since 1.0.0
     */
    private _getMeasuredWidth(text: string): number {
        let ctx = this.context;
        //ctx.save();
        let w = ctx.measureText(text).width;
        //ctx.restore();
        return w;
    }
    private realLines: string[] = [];
    /**
     * 更新文本，主要重画canvas
     */
    public updateText(): void {
        let s: TextField = this;
        if (!s.dirty) return;
        s.dirty = false;
        //如果没有文本
        if (!s._text) {
            s.canvas.width = 0;
            s.canvas.height = 0;
            s._localBoundsSelf.clear();
            s.anchorTexture.set(0, 0)// = { x: 0, y: 0 };
            s.texture.update()
            return
        }
        s._text += "";
        let can = s.canvas;
        let ctx = s.context;
        let hardLines: any = s._text.toString().split(/(?:\r\n|\r|\n)/);
        let realLines: any = [];
        s.realLines = realLines;
        s._prepContext(ctx);//要先执行，下面有些测量文本的操作

        let textWidth = s._textWidth;
        // let lineH = s._lineSpacing + s.size;
        //单行文本时
        if (s._text.indexOf("\n") < 0 && s.lineType == TEXT_lINETYPE.SINGLE) {
            realLines[realLines.length] = hardLines[0];
            let str = hardLines[0];
            let lineW = s._getMeasuredWidth(str);
            //如果没设置过textWidth就取lineW
            textWidth = textWidth || lineW;
            //如果设置过textWidth的。截取文本
            if (lineW > textWidth) {
                let w = s._getMeasuredWidth(str[0]);
                let lineStr = str[0];
                let wordW = 0;
                let strLen = str.length;
                for (let j = 1; j < strLen; j++) {
                    wordW = s._getMeasuredWidth(str[j])//ctx.measureText(str[j]).width;
                    w += wordW;
                    if (w > textWidth) {
                        realLines[0] = lineStr;
                        break;
                    } else {
                        lineStr += str[j];
                    }
                }
            }
        } else {
            //textWidth取每行最大值，如果没设置过textWidth
            if (!textWidth) {
                for (let i = 0, l = hardLines.length; i < l; i++) {
                    let str = hardLines[i];
                    if (!str) continue;
                    textWidth = Math.max(s._getMeasuredWidth(str), textWidth);
                }
            }
            for (let i = 0, l = hardLines.length; i < l; i++) {
                let str = hardLines[i];
                if (!str) continue;
                let w = s._getMeasuredWidth(str[0]);
                let lineStr = str[0];
                let wordW = 0;
                let strLen = str.length;
                for (let j = 1; j < strLen; j++) {
                    wordW = s._getMeasuredWidth(str[j]) //ctx.measureText(str[j]).width;
                    w += wordW;
                    if (w > textWidth) {
                        realLines[realLines.length] = lineStr;
                        lineStr = str[j];
                        w = wordW;
                    } else {
                        lineStr += str[j];
                    }
                }
                realLines[realLines.length] = lineStr;
            }
        }
        // let maxH = lineH * realLines.length;
        var trueHeight: number = s.size * realLines.length + s._lineSpacing * (realLines.length - 1);
        let maxH = s._textHeight || trueHeight;
        let maxW = textWidth;
        let tx = 0;
        if (s._textAlign == TEXT_ALIGN.CENTER) {
            tx = maxW * 0.5;
        } else if (s._textAlign == TEXT_ALIGN.RIGHT) {
            tx = maxW;
        }
        can.width = maxW + padding * 2;
        can.height = maxH + padding * 2;
        ctx.clearRect(0, 0, can.width, can.height);
        if (s.border) {
            ctx.beginPath();
            ctx.strokeStyle = "#000";
            ctx.lineWidth = 1;
            ctx.strokeRect(padding + 0.5, padding + 0.5, maxW, maxH);
            ctx.closePath();
        }
        ctx.setTransform(1, 0, 0, 1, tx + padding, padding);
        s._prepContext(ctx);//必须再执行一边，因为canvas尺寸改变过，上下文状态机会重置
        let lineH = s._lineSpacing + s.size;
        //如果有_textHeight,就需要应用竖直对齐
        var upY: number = 0;
        if (s._textHeight) {
            //跟trueHeight比较
            if (s._verticalAlign == VERTICAL_ALIGN.MIDDLE) {
                upY = (s._textHeight - trueHeight) * 0.5;
            } else if (s._verticalAlign == VERTICAL_ALIGN.DOWN) {
                upY = s._textHeight - trueHeight;
            }
        }
        for (let i = 0; i < realLines.length; i++) {
            if (s.stroke) {
                ctx.strokeStyle = s.strokeColor;
                ctx.lineWidth = s.stroke * 2;
                ctx.strokeText(realLines[i], 0, upY + i * lineH, maxW);
            }
            ctx.fillText(realLines[i], 0, upY + i * lineH, maxW);
        }
        //offset用_anchorTexture代替
        s.offsetX = -padding;
        s.offsetY = -padding;

        this.anchorTexture.set((padding + 0.5) / can.width, padding / can.height) //= { x: (padding + 0.5) / can.width, y: padding / can.height }

        // document.body.appendChild(can)

        //修改texture及baseTexture属性
        s.texture.update();

        //里面会计时localBoundSelf
        s._onTextureUpdate();
    }




    _renderCanvas(renderer) {
        this.updateText();
        super._renderCanvas(renderer);
    }
    _renderWebGL(renderer) {
        this.updateText();
        super._renderWebGL(renderer)
    }

    public destroy(): void {
        super.destroy();
        //todo
    }
}
