/**
 * canvas相关接口、类
 */
import {is, checkParam, compareVersion} from "./util/commonFn";
import {callNativeSync} from "./util";
import shortId from 'shortid';

// 判断运行环境
function judgeEnv() {
    let output = {
        env: '',
        isDowngrade: false
    };
    if (global.document) {
        if (global.__SmallApp_env_run_type) {
            if (global.__SmallApp_env_run_type === 2) {
                output.env = 'Service';
                output.isDowngrade = true;
            } else if (global.__SmallApp_env_run_type === 5) {
                output.env = 'Render';
            } else if (global.__SmallApp_env_run_type === 6) {
                output.env = 'Render';
                output.isDowngrade = true;
            }
        } else {
            output.env = 'Render';
        }
    } else {
        output.env = 'Service';
    }
    return output;
}

// 消费canvas指令
function consumptionQueue(id, param = {
    class: '',
    type: '',
    name: '',
    arguments: []
}) {
    let runEnv = judgeEnv();
    const pageId = global.__biliCacheData.getCurrentPageId();
    let _readyCanvas = global.canvas[pageId][id];
    let _canvasCallback = global.canvas.callback;
    // 主动捕获运行中存在的问题
    try {
        let _canvas = global.canvas[pageId][id].canvas;
        let _ctx = global.canvas[pageId][id].ctx;
        let _canvasGrd = global.canvas.grd;

        if (runEnv.env === 'Service' && !runEnv.isDowngrade) {
            if (_readyCanvas.status === 'ready') {
                if (param.class === 'ctx') {
                    if (param.type === 'function') {
                        // 有上下文
                        if (param.callerId) {
                            // 缓存渐变对象上下文
                            if (!_canvasGrd) _canvasGrd = {};
                            _canvasGrd[param.callerId] = _ctx[param.name](...param.arguments);
                        } else if (param.callerType === 'return') {
                            try {
                                if (param.name === 'putImageData') {
                                    let tempArg = param.arguments[0];
                                    let tempImageData = _ctx.createImageData(tempArg.width, tempArg.height, tempArg.data);
                                    _ctx[param.name](tempImageData, tempArg.x, tempArg.y);
                                    if (param.callback.success) {
                                        setTimeout(() => {
                                            const outputValue = {
                                                errMsg: param.name + ':ok'
                                            };
                                            _canvasCallback[param.callback.success](outputValue);
                                        }, 0);
                                    }
                                } else {
                                    let temp = _ctx[param.name](...param.arguments);
                                    if (param.callback.success) {
                                        setTimeout(() => {
                                            const outputValue = {
                                                errMsg: param.name + ':ok'
                                            };
                                            global.tempData = temp;
                                            let outputTemp = null;
                                            if (typeof temp === 'object' && !Array.isArray(temp)) {
                                                outputTemp = Object.assign(temp, outputValue);
                                            } else if (temp === undefined || temp === null) {
                                                outputTemp = outputValue;
                                            } else {
                                                outputTemp = temp;
                                            }
                                            _canvasCallback[param.callback.success](outputTemp);
                                        }, 0);
                                    }
                                }
                            } catch (e) {
                                if (param.callback.fail) {
                                    setTimeout(() => {
                                        const outputValue = {
                                            errMsg: param.name + ':fail ' + e.message
                                        };
                                        _canvasCallback[param.callback.fail](outputValue);
                                    }, 0);
                                }
                            } finally {
                                if (param.callback.complete) {
                                    setTimeout(() => {
                                        const outputValue = {
                                            errMsg: param.name + ':complete'
                                        };
                                        _canvasCallback[param.callback.complete](outputValue);
                                    }, 0);
                                }
                            }
                        } else {
                            _ctx[param.name](...param.arguments);
                        }
                    } else if (param.type === 'property') {
                        if (is.Object(param.arguments)) {
                            if (param.arguments.grd) {
                                _ctx[param.name] = _canvasGrd[param.arguments.grd];
                            } else {
                                _ctx[param.name] = param.arguments;
                            }
                        } else {
                            _ctx[param.name] = param.arguments;
                        }
                    } else if (param.type === 'callback') {
                        // 在queue队列中，需要处理完，立马调用回调。
                        _canvasCallback[param.callerId]();
                    }
                } else if (param.class === 'canvas') {
                    if (param.type === 'function') {
                        _canvas[param.name](...param.arguments);
                    } else if (param.type === 'property') {
                        _canvas[param.name] = param.arguments;
                    }
                } else if (param.class === 'grd') {
                    if (_canvasGrd && _canvasGrd[param.caller]) {
                        _canvasGrd[param.caller][param.name](...param.arguments);
                    }
                }
            }
        }
    } catch (e) {
        // 方案回补，保证其他指令能完成：清除正在执行queue队列，且将错误暴露出来。
        console.error('canvas:fail - ', param.name);
        console.error('canvas:error - ', e.message);
        _readyCanvas.queue = [];
    }

}

/**
 * 运行 content api
 *  if canvas init ok  ==> ctx run
 *      else      ==> push queue
 * */
function runCanvas(id, param = {
    class: '',
    type: '',
    name: '',
    arguments: []
}) {
    // 临时temp缓存是否存在，存在说明没隔离好
    if (global.canvas[id]) {
        global.canvas[id].preQueue.push(param);
    } else {
        const pageId = global.__biliCacheData.getCurrentPageId();
        if (global.canvas[pageId] && global.canvas[pageId][id]) {
            global.canvas[pageId][id].preQueue.push(param);
        }
    }
}

class CanvasGradient {
    constructor(canvasId, id) {
        this.__canvasId = canvasId;
        this.__id = id;
    }

    addColorStop() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'stop',
                type: 'Number'
            },
            {
                key: 'color',
                type: 'String'
            }
        ], {name: 'addColorStop'});

        if (isOk) {
            runCanvas(this.__canvasId, {
                class: 'grd',
                type: 'function',
                name: 'addColorStop',
                arguments: temp,
                caller: this.__id
            });
        }
    }
}

class Pattern {
    constructor(canvasId, id) {
        this.__canvasId = canvasId;
        this.__id = id;
    }
}

/**
 * Canvas类
 * 唯一标识 __canvasId 标记初始化的video唯一标识
 *
 * @class CanvasContext
 */
class CanvasContext {

    constructor(id) {
        let fillStyle = '#000000';
        let strokeStyle = '#000000';
        let shadowOffsetX = 0;
        let shadowOffsetY = 0;
        let shadowColor = 'rgba(0, 0, 0, 0)';
        let shadowBlur = 0;
        let lineWidth = 1;
        let lineCap = 'butt';
        let lineJoin = 'miter';
        let miterLimit = 10;
        let lineDashOffset = 0;
        let font = '10px sans-serif';
        let globalAlpha = 1;
        let globalCompositeOperation = 'source-over';
        let textAlign = 'start';
        let textBaseline = 'alphabetic';

        // 属性劫持
        Object.defineProperties(this, {
            __id: {
                value: id,
                writable: false,
                enumerable: false,
                configurable: false
            },
            fillStyle: {
                get() {
                    return fillStyle;
                },
                set(value) {
                    if (value === null) return;
                    // api 参数类型校验
                    const isOk = checkParam([value], [
                        {
                            key: 'fillStyle',
                            type: ['String', 'Object']
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        fillStyle = value;
                        let tempParam = null;
                        if (is.Object(value)) {
                            tempParam = {
                                grd: value.__id
                            };
                        } else if (is.String(value)) {
                            tempParam = value;
                        }
                        // 指令需要缓存
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'fillStyle',
                            arguments: tempParam
                        });
                    }

                },
                enumerable: true,
            },
            strokeStyle: {
                get() {
                    return strokeStyle;
                },
                set(value) {
                    if (value === null) return;
                    const isOk = checkParam([value], [
                        {
                            key: 'strokeStyle',
                            type: ['String', 'Object']
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        strokeStyle = value;
                        let tempParam = null;
                        if (is.Object(value)) {
                            tempParam = tempParam = {
                                grd: value.__id
                            };
                        } else if (is.String(value)) {
                            tempParam = value;
                        }
                        // 指令需要缓存
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'strokeStyle',
                            arguments: tempParam
                        });
                    }

                },
                enumerable: true,
            },
            shadowOffsetX: {
                get() {
                    return shadowOffsetX;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'shadowOffsetX',
                            type: 'Number'
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        shadowOffsetX = value;
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'shadowOffsetX',
                            arguments: value
                        });
                    }
                },
                enumerable: true,
            },
            shadowOffsetY: {
                get() {
                    return shadowOffsetY;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'shadowOffsetY',
                            type: 'Number'
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        shadowOffsetY = value;
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'shadowOffsetY',
                            arguments: value
                        });
                    }
                },
                enumerable: true,
            },
            shadowColor: {
                get() {
                    return shadowColor;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'shadowColor',
                            type: 'String'
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        shadowColor = value;
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'shadowColor',
                            arguments: value
                        });
                    }
                },
                enumerable: true,
            },
            shadowBlur: {
                get() {
                    return shadowBlur;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'shadowColor',
                            type: 'Number'
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        shadowBlur = value;
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'shadowBlur',
                            arguments: value
                        });
                    }
                },
                enumerable: true,
            },
            lineWidth: {
                get() {
                    return lineWidth;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'lineWidth',
                            type: 'Number'
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        lineWidth = value;
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'lineWidth',
                            arguments: value
                        });
                    }
                },
                enumerable: true
            },
            lineCap: {
                get() {
                    return lineCap;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'lineCap',
                            type: 'String'
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        lineCap = value;
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'lineCap',
                            arguments: value
                        });
                    }
                },
                enumerable: true,
            },
            lineJoin: {
                get() {
                    return lineJoin;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'lineJoin',
                            type: 'String'
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        lineJoin = value;
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'lineJoin',
                            arguments: value
                        });
                    }
                },
                enumerable: true,
            },
            miterLimit: {
                get() {
                    return miterLimit;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'miterLimit',
                            type: 'Number'
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        miterLimit = value;
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'miterLimit',
                            arguments: value
                        });
                    }
                },
                enumerable: true,
            },
            lineDashOffset: {
                get() {
                    return lineDashOffset;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'lineDashOffset',
                            type: 'Number'
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        lineDashOffset = value;
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'lineDashOffset',
                            arguments: value
                        });
                    }
                },
                enumerable: true,
            },
            font: {
                get() {
                    return font;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'font',
                            type: ['String', 'Number']
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        // 兼容纯数字
                        if (is.Number(value)){
                            font = font.replace(/[0-9]+px/, value + 'px');
                        } else {
                            font = value;
                        }

                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'font',
                            arguments: font
                        });
                    }

                },
                enumerable: true,
            },
            globalAlpha: {
                get() {
                    return globalAlpha;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'globalAlpha',
                            type: 'Number'
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        globalAlpha = value;
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'globalAlpha',
                            arguments: value
                        });
                    }
                },
                enumerable: true,
            },
            globalCompositeOperation: {
                get() {
                    return globalCompositeOperation;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'globalCompositeOperation',
                            type: 'String'
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        globalCompositeOperation = value;
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'globalCompositeOperation',
                            arguments: value
                        });
                    }
                },
                enumerable: true,
            },
            textAlign: {
                get() {
                    return textAlign;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'textAlign',
                            type: 'String'
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        textAlign = value;
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'textAlign',
                            arguments: value
                        });
                    }

                },
                enumerable: true,
            },
            textBaseline: {
                get() {
                    return textBaseline;
                },
                set(value) {
                    const isOk = checkParam([value], [
                        {
                            key: 'textBaseline',
                            type: 'String'
                        }
                    ], {name: 'property'});

                    if (isOk) {
                        // 兼容微信写法
                        if (value === 'normal') {
                            value = 'alphabetic';
                        }
                        textBaseline = value;
                        runCanvas(this.__id, {
                            class: 'ctx',
                            type: 'property',
                            name: 'textBaseline',
                            arguments: value
                        });
                    }
                },
                enumerable: true,
            },
        });

        this.resetCanvas = function () {
            fillStyle = '#000000';
            strokeStyle = '#000000';
            shadowOffsetX = 0;
            shadowOffsetY = 0;
            shadowColor = 'rgba(0, 0, 0, 0)';
            shadowBlur = 0;
            lineWidth = 1;
            lineCap = 'butt';
            lineJoin = 'miter';
            miterLimit = 10;
            lineDashOffset = 0;
            font = '10px sans-serif';
            globalAlpha = 1;
            globalCompositeOperation = 'source-over';
            textAlign = 'start';
            textBaseline = 'alphabetic';
        };

        this._pageId = global.__biliCacheData.getCurrentPageId();
    }

    arc() {
        let temp = Array.prototype.slice.apply(arguments);
        let checkRule = [
            {
                key: 'x',
                type: 'Number'
            },
            {
                key: 'y',
                type: 'Number'
            },
            {
                key: 'r',
                type: 'Number'
            },
            {
                key: 'sAngle',
                type: 'Number'
            },
            {
                key: 'eAngle',
                type: 'Number'
            }
        ];

        if (temp.length >= 6) {
            // 可选参数兜底，非Boolean，则默认为false。
            if (!is.Boolean(temp[5])) {
                temp[5] = false;
            }
            checkRule.push({
                key: 'counterclockwise',
                type: 'Boolean'
            });
        }

        // api 参数类型校验
        const isOk = checkParam(temp, checkRule, {name: 'arc'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'arc',
                arguments: temp
            });
        }
    }

    arcTo() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'x1',
                type: 'Number'
            },
            {
                key: 'y1',
                type: 'Number'
            },
            {
                key: 'x2',
                type: 'Number'
            },
            {
                key: 'y2',
                type: 'Number'
            },
            {
                key: 'radius',
                type: 'Number'
            }
        ], {name: 'arcTo'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'arcTo',
                arguments: temp
            });
        }
    }

    beginPath() {
        runCanvas(this.__id, {
            class: 'ctx',
            type: 'function',
            name: 'beginPath',
            arguments: []
        });
    }

    bezierCurveTo() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'cp1x',
                type: 'Number'
            },
            {
                key: 'cp1y',
                type: 'Number'
            },
            {
                key: 'cp2x',
                type: 'Number'
            },
            {
                key: 'cp2y',
                type: 'Number'
            },
            {
                key: 'x',
                type: 'Number'
            },
            {
                key: 'y',
                type: 'Number'
            }
        ], {name: 'bezierCurveTo'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'bezierCurveTo',
                arguments: temp
            });
        }
    }

    clearRect() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'x',
                type: 'Number'
            },
            {
                key: 'y',
                type: 'Number'
            },
            {
                key: 'width',
                type: 'Number'
            },
            {
                key: 'height',
                type: 'Number'
            }
        ], {name: 'clearRect'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'clearRect',
                arguments: temp
            });
        }
    }

    clip() {
        runCanvas(this.__id, {
            class: 'ctx',
            type: 'function',
            name: 'clip',
            arguments: []
        });
    }

    closePath() {
        runCanvas(this.__id, {
            class: 'ctx',
            type: 'function',
            name: 'closePath',
            arguments: []
        });
    }

    createCircularGradient() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'x',
                type: 'Number'
            },
            {
                key: 'y',
                type: 'Number'
            },
            {
                key: 'r',
                type: 'Number'
            }
        ], {name: 'createCircularGradient'});
        if (isOk) {
            let tempId = shortId.generate();
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'createRadialGradient',
                arguments: [temp[0], temp[1], 0, ...temp],
                callerId: tempId
            });
            return new CanvasGradient(this.__id, tempId);
        }
    }

    createLinearGradient() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'x0',
                type: 'Number'
            },
            {
                key: 'y0',
                type: 'Number'
            },
            {
                key: 'x1',
                type: 'Number'
            },
            {
                key: 'y1',
                type: 'Number'
            }
        ], {name: 'createLinearGradient'});

        if (isOk) {
            let tempId = shortId.generate();
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'createLinearGradient',
                arguments: temp,
                callerId: tempId
            });
            return new CanvasGradient(this.__id, tempId);
        }
    }

    createPattern() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'image',
                type: 'String'
            },
            {
                key: 'repetition',
                type: 'String'
            }
        ], {name: 'createPattern'});

        if (isOk) {
            if (temp[1] === 'repeat' || temp[1] === 'no-repeat' || temp[1] === 'repeat-x' || temp[1] === 'repeat-y') {
                let tempShortId = shortId.generate();
                if (!judgeEnv().isDowngrade) {
                    let image = global.__biliComponentData.canvas.canvasForNA().createImage();
                    image.loadFromLocal(temp[0]);
                    runCanvas(this.__id, {
                        class: 'ctx',
                        type: 'function',
                        name: 'createPattern',
                        callerId: tempShortId,
                        arguments: [image, temp[1]]
                    });
                    image.onerror = function (e) {
                        console.error('createPattern: fail ', e);
                    };
                } else {
                    runCanvas(this.__id, {
                        class: 'ctx',
                        type: 'function',
                        name: 'createPattern',
                        isImage: true,
                        callerId: tempShortId,
                        arguments: temp
                    });
                }
                return new Pattern(this.__id, tempShortId);
            } else {
                console.error(`Failed to execute 'createPattern' on 'CanvasContent': The provided type (${temp[1]}) is not one of 'repeat', 'no-repeat', 'repeat-x', or 'repeat-y'.`);
            }
        }
    }

    // 绘制，注意降级
    draw() {
        let temp = Array.prototype.slice.apply(arguments);
        let runEnv = judgeEnv();
        const pageId = global.__biliCacheData.getCurrentPageId();

        // 报错兜底，如果用户进入页面快速退出，导致Service层还在执行页面的东西，报错兜底。
        if (this._pageId !== pageId) return;
        if (!global.canvas[this.__id] && !(global.canvas[pageId] && global.canvas[pageId][this.__id])) return;

        let noCacheCanvas = global.canvas[this.__id];
        let readyCanvas = global.canvas[pageId] ? global.canvas[pageId][this.__id] : null;
        let tempId = shortId.generate();
        if (!global.canvas.callback) global.canvas.callback = {};

        // 参数做兜底
        if (temp.length === 0) {
            temp[0] = false;
        } else if (temp.length === 1) {
            if (!(temp[0] === true)) temp[0] = false;
            temp[1] = null;
        } else if (temp.length === 2) {
            if (temp[0] !== true) temp[0] = false;
            if (typeof temp[1] !== 'function') temp[1] = null;
        }

        if (temp[1]) global.canvas.callback[tempId] = temp[1];
        if (noCacheCanvas) {
            // clearRect 现阶段还获取不到canvas宽高，只能render ok后替换
            const noReadyClear = [
                {
                    class: 'ctx',
                    type: 'function',
                    name: 'resetCurrentState',
                    arguments: []
                },
                {
                    class: 'ctx',
                    type: 'function',
                    isInit: true,
                    name: 'clearRect',
                    arguments: [0, 0, 'noWidth', 'noHeight']
                }
            ];
            if (temp[0] === false) {

                if (runEnv.isDowngrade) {
                    noCacheCanvas.preQueue.unshift({
                        class: 'global',
                        type: 'clear',
                    });
                } else {
                    noCacheCanvas.preQueue.unshift(...noReadyClear);
                }
                this.resetCanvas();
            }

            // callback 存在的时候
            if (temp[1]) {
                noCacheCanvas.preQueue.push({
                    class: 'ctx',
                    type: 'callback',
                    callerId: tempId,
                    arguments: []
                });
            }

            noCacheCanvas.queue = noCacheCanvas.queue.concat(noCacheCanvas.preQueue);
            noCacheCanvas.preQueue = [];
        } else {
            const readyClear = [
                {
                    class: 'ctx',
                    type: 'function',
                    name: 'resetCurrentState',
                    arguments: []
                },
                {
                    class: 'ctx',
                    type: 'function',
                    name: 'clearRect',
                    arguments: [0, 0, readyCanvas.style.width, readyCanvas.style.height]
                }
            ];
            if (temp[0] === false) {
                if (runEnv.isDowngrade) {
                    readyCanvas.preQueue.unshift({
                        class: 'global',
                        type: 'clear',
                    });
                } else {
                    readyCanvas.preQueue.unshift(...readyClear);
                }
                this.resetCanvas();
            }

            // 如果callback存在
            if (temp[1]) {
                readyCanvas.preQueue.push({
                    class: 'ctx',
                    type: 'callback',
                    callerId: tempId,
                    arguments: []
                });
            }

            readyCanvas.queue = readyCanvas.queue.concat(readyCanvas.preQueue);
            readyCanvas.preQueue = [];
            // 非降级逻辑
            if (!runEnv.isDowngrade) {
                readyCanvas.queue.forEach(x => {
                    consumptionQueue(this.__id, x);
                });
                readyCanvas.queue = [];
            }
        }

        // Service层降级方案
        if (runEnv.env === 'Service' && runEnv.isDowngrade) {
            if (!noCacheCanvas) {
                Service.postMessage(JSON.stringify({
                    type: 'canvas',
                    canvasId: this.__id,
                    isNewCreate: readyCanvas.isNewCreate,
                    data: readyCanvas.queue,
                    style: readyCanvas.style
                }), pageId);
                readyCanvas.queue = [];
            }
        }
    }

    drawImage() {
        let temp = Array.prototype.slice.apply(arguments);
        let ruleTemp = [];
        let checkRule = [
            {
                key: 'imageResource',
                type: 'String'
            },
            {
                key: 'dx',
                type: 'Number'
            },
            {
                key: 'dy',
                type: 'Number'
            }];
        if (temp.length > 3 && temp.length < 6) {
            ruleTemp = [
                {
                    key: 'dWidth',
                    type: 'Number'
                },
                {
                    key: 'dHeight',
                    type: 'Number'
                }
            ];
            checkRule = checkRule.concat(ruleTemp);
        } else if (temp.length >= 6) {
            ruleTemp = [
                {
                    key: 'dWidth',
                    type: 'Number'
                },
                {
                    key: 'dHeight',
                    type: 'Number'
                },
                {
                    key: 'sx',
                    type: 'Number'
                },
                {
                    key: 'sy',
                    type: 'Number'
                },
                {
                    key: 'sWidth',
                    type: 'Number'
                },
                {
                    key: 'sHeight',
                    type: 'Number'
                }
            ];
            checkRule = checkRule.concat(ruleTemp);
        }

        // api 参数类型校验
        const isOk = checkParam(temp, checkRule, {name: 'drawImage'});
        if (isOk) {
            let tempId = this.__id;
            if (!judgeEnv().isDowngrade) {
                let image = global.__biliComponentData.canvas.canvasForNA().createImage();
                image.loadFromLocal(temp[0]);
                runCanvas(tempId, {
                    class: 'ctx',
                    type: 'function',
                    name: 'drawImage',
                    arguments: [image, ...temp.filter((x, i) => {
                        return i > 0;
                    })]
                });
                image.onerror = function (e) {
                    console.error('drawImage: fail ', e);
                };
            } else {
                runCanvas(tempId, {
                    class: 'ctx',
                    type: 'function',
                    name: 'drawImage',
                    isImage: true,
                    arguments: temp
                });
            }
        }
    }

    fill() {
        runCanvas(this.__id, {
            class: 'ctx',
            type: 'function',
            name: 'fill',
            arguments: []
        });
    }

    fillRect() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'x',
                type: 'Number'
            },
            {
                key: 'y',
                type: 'Number'
            },
            {
                key: 'width',
                type: 'Number'
            },
            {
                key: 'height',
                type: 'Number'
            }
        ], {name: 'fillRect'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'fillRect',
                arguments: temp
            });
        }
    }

    fillText() {
        let temp = Array.prototype.slice.apply(arguments);
        let checkRule = [
            {
                key: 'text',
                type: 'String'
            },
            {
                key: 'x',
                type: 'Number'
            },
            {
                key: 'y',
                type: 'Number'
            }
        ];
        if (temp.length >= 4) {
            checkRule.push({
                key: 'maxWidth',
                type: 'Number'
            });
        }


        // api 参数类型校验
        const isOk = checkParam(temp, checkRule, {name: 'fillText'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'fillText',
                arguments: temp
            });
        }
    }

    lineTo() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'x',
                type: 'Number'
            },
            {
                key: 'y',
                type: 'Number'
            }
        ], {name: 'lineTo'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'lineTo',
                arguments: temp
            });
        }
    }

    // 同步方案：需要直接从离屏canvas 获取
    measureText() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'text',
                type: 'String'
            }
        ], {name: 'measureText'});

        if (isOk && global.canvas.OffscreenCanvas) {
            global.canvas.OffscreenCanvas.ctx.font = this.font;
            return global.canvas.OffscreenCanvas.ctx.measureText(temp[0]);
        }
    }

    moveTo() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'x',
                type: 'Number'
            },
            {
                key: 'y',
                type: 'Number'
            }
        ], {name: 'moveTo'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'moveTo',
                arguments: temp
            });
        }
    }

    quadraticCurveTo() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'cpx',
                type: 'Number'
            },
            {
                key: 'cpy',
                type: 'Number'
            },
            {
                key: 'x',
                type: 'Number'
            },
            {
                key: 'y',
                type: 'Number'
            }
        ], {name: 'quadraticCurveTo'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'quadraticCurveTo',
                arguments: temp
            });
        }
    }

    rect() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'x',
                type: 'Number'
            },
            {
                key: 'y',
                type: 'Number'
            },
            {
                key: 'width',
                type: 'Number'
            },
            {
                key: 'height',
                type: 'Number'
            }
        ], {name: 'rect'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'rect',
                arguments: temp
            });
        }
    }

    restore() {
        runCanvas(this.__id, {
            class: 'ctx',
            type: 'function',
            name: 'restore',
            arguments: []
        });
    }

    rotate() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'rotate',
                type: 'Number'
            }
        ], {name: 'rotate'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'rotate',
                arguments: temp
            });
        }
    }

    save() {
        runCanvas(this.__id, {
            class: 'ctx',
            type: 'function',
            name: 'save',
            arguments: []
        });
    }

    scale() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'scaleWidth',
                type: 'Number'
            },
            {
                key: 'scaleHeight',
                type: 'Number'
            }
        ], {name: 'scale'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'scale',
                arguments: temp
            });
        }
    }

    setFillStyle() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'color',
                type: ['String', 'Object']
            }
        ], {name: 'setFillStyle'});

        if (isOk) {
            this.fillStyle = temp[0];
        }
    }

    setFontSize() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'fontSize',
                type: 'Number'
            }
        ], {name: 'setFontSize'});

        if (isOk) {
            this.font = this.font.replace(/[0-9]+px/, temp[0] + 'px');
        }
    }

    setGlobalAlpha() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'alpha',
                type: 'Number'
            }
        ], {name: 'setGlobalAlpha'});

        if (isOk) {
            this.globalAlpha = temp[0];
        }
    }

    setLineCap() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'lineCap',
                type: 'String'
            }
        ], {name: 'setLineCap'});

        if (isOk) {
            this.lineCap = temp[0];
        }
    }

    setLineDash() {
        let temp = Array.prototype.slice.apply(arguments);

        // 容错，第二个参数默认为0。
        if (temp.length === 1) {
            temp.push(0);
        }

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'pattern',
                type: 'Array'
            },
            {
                key: 'offset',
                type: 'Number'
            }
        ], {name: 'setLineDash'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'setLineDash',
                arguments: [temp[0]]
            });
            this.lineDashOffset = temp[1];
        }
    }

    setLineJoin() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'lineJoin',
                type: 'String'
            }
        ], {name: 'setLineJoin'});

        if (isOk) {
            this.lineJoin = temp[0];
        }
    }

    setLineWidth() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'lineWidth',
                type: 'Number'
            }
        ], {name: 'setLineWidth'});

        if (isOk) {
            this.lineWidth = temp[0];
        }
    }

    setMiterLimit() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'miterLimit',
                type: 'Number'
            }
        ], {name: 'setMiterLimit'});

        if (isOk) {
            this.miterLimit = temp[0];
        }
    }

    setShadow() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'offsetX',
                type: 'Number'
            },
            {
                key: 'offsetY',
                type: 'Number'
            },
            {
                key: 'blur',
                type: 'Number'
            },
            {
                key: 'color',
                type: ['String', 'Object']
            }
        ], {name: 'setShadow'});

        if (isOk) {
            this.shadowOffsetX = temp[0];
            this.shadowOffsetY = temp[1];
            this.shadowBlur = temp[2];
            this.shadowColor = temp[3];
        }
    }

    setStrokeStyle() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'color',
                type: ['String', 'Object']
            }
        ], {name: 'setStrokeStyle'});

        if (isOk) {
            this.strokeStyle = temp[0];
        }
    }

    setTextAlign() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'align',
                type: 'String'
            }
        ], {name: 'setTextAlign'});

        if (isOk) {
            this.textAlign = temp[0];
        }
    }

    setTextBaseline() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'textBaseline',
                type: 'String'
            }
        ], {name: 'setTextBaseline'});

        if (isOk) {
            this.textBaseline = temp[0];
        }
    }

    setTransform() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'scaleX',
                type: 'Number'
            },
            {
                key: 'skewX',
                type: 'Number'
            },
            {
                key: 'skewY',
                type: 'Number'
            },
            {
                key: 'scaleY',
                type: 'Number'
            },
            {
                key: 'translateX',
                type: 'Number'
            },
            {
                key: 'translateY',
                type: 'Number'
            }
        ], {name: 'setTransform'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'setTransform',
                arguments: temp
            });
        }
    }

    stroke() {
        runCanvas(this.__id, {
            class: 'ctx',
            type: 'function',
            name: 'stroke',
            arguments: []
        });
    }

    strokeRect() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'x',
                type: 'Number'
            },
            {
                key: 'y',
                type: 'Number'
            },
            {
                key: 'width',
                type: 'Number'
            },
            {
                key: 'height',
                type: 'Number'
            }
        ], {name: 'strokeRect'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'strokeRect',
                arguments: temp
            });
        }
    }

    strokeText() {
        let temp = Array.prototype.slice.apply(arguments);
        let checkRule = [
            {
                key: 'text',
                type: 'String'
            },
            {
                key: 'x',
                type: 'Number'
            },
            {
                key: 'y',
                type: 'Number'
            }
        ];
        if (temp.length >= 4) {
            checkRule.push({
                key: 'maxWidth',
                type: 'Number'
            });
        }


        // api 参数类型校验
        const isOk = checkParam(temp, checkRule, {name: 'strokeText'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'strokeText',
                arguments: temp
            });
        }
    }

    transform() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'scaleX',
                type: 'Number'
            },
            {
                key: 'skewX',
                type: 'Number'
            },
            {
                key: 'skewY',
                type: 'Number'
            },
            {
                key: 'scaleY',
                type: 'Number'
            },
            {
                key: 'translateX',
                type: 'Number'
            },
            {
                key: 'translateY',
                type: 'Number'
            }
        ], {name: 'transform'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'transform',
                arguments: temp
            });
        }
    }

    translate() {
        let temp = Array.prototype.slice.apply(arguments);

        // api 参数类型校验
        const isOk = checkParam(temp, [
            {
                key: 'x',
                type: 'Number'
            },
            {
                key: 'y',
                type: 'Number'
            }
        ], {name: 'translate'});

        if (isOk) {
            runCanvas(this.__id, {
                class: 'ctx',
                type: 'function',
                name: 'translate',
                arguments: temp
            });
        }
    }
}

/**
 * 适配canvas对象NA注入调用兼容
 * @return {{createImage: *, createCanvas: *}|null}
 */
function NACanvas() {
    const systemInfo = callNativeSync('getSystemInfoSync')["data"];
    if (compareVersion(systemInfo.SDKVersion, '3.18.0') >= 0) {
        if (systemInfo.platform === 'android') {
            return {
                createCanvas: global.createCanvas,
                createImage: global.createImage
            };
        } else {
            if (global.BLGlobal && global.BLGlobal.createCanvas) {
                return {
                    createCanvas: global.BLGlobal.createCanvas.bind(global.BLGlobal),
                    createImage: global.BLGlobal.createImage.bind(global.BLGlobal)
                };
            }
        }
    } else {
        console.warn('canvas does not support,please use SDKVersion 3.18.0 or above.');
        return null;
    }
}

if (judgeEnv().env === 'Service' && !judgeEnv().isDowngrade) {
    // 放到全局方便使用
    global.__biliComponentData.canvas.canvasForNA = NACanvas;
    global.canvasForNA = NACanvas();
}

export default {
    createOffscreenCanvas(object = {
        type: 'webgl',
        width: 0,
        height: 0
    }) {
        let _NACanvas = global.__biliComponentData.canvas.canvasForNA();
        let offscreenCanvas = _NACanvas.createCanvas(true, global.__biliCacheData.getCurrentPageId(), 2);
        offscreenCanvas.createImage = global.__biliComponentData.canvas.canvasForNA().createImage;
        offscreenCanvas.width = object.width;
        offscreenCanvas.height = object.height;
        return offscreenCanvas;
    },
    /**
     * 创建内部 CanvasContext类 上下文 createCanvas Context 对象。
     *
     * @returns {CanvasContext}
     */
    createCanvasContext(id) {
        if (!is.String(id)) {
            console.error(`[bl warn]: Invalid parameter: type check failed for parameter "id" in "bl.createCanvasContext". Expected String, got ${is.getType(id)} with value false.`);
        } else {
            // 低版本兼容不报错
            let _NACanvas = global.__biliComponentData.canvas.canvasForNA();
            if (_NACanvas || judgeEnv().isDowngrade) {
                if (!global.canvas) global.canvas = {};
                let runEnv = judgeEnv();
                if (!global.canvas["OffscreenCanvas"]) {
                    global.canvas["OffscreenCanvas"] = {};
                    // Service层，不降级
                    if (runEnv.env === 'Service' && !runEnv.isDowngrade) {
                        // 初始化离屏canvas，供同步方法使用
                        let offscreenCanvas = _NACanvas.createCanvas(true);
                        global.canvas["OffscreenCanvas"].canvas = offscreenCanvas;
                        global.canvas["OffscreenCanvas"].ctx = offscreenCanvas.getContext('2d');
                    } else {
                        // 安卓降级方案
                        let offscreenCanvas = global.document.createElement('canvas');
                        global.canvas["OffscreenCanvas"].canvas = offscreenCanvas;
                        global.canvas["OffscreenCanvas"].ctx = offscreenCanvas.getContext('2d');
                    }
                }
                let _noCanvas = global.canvas[id];
                // 相同canvas id，且已经初始化过。
                if (_noCanvas) {
                    if (_noCanvas.instance) return _noCanvas.instance;
                    let canvasInstance = new CanvasContext(id);
                    _noCanvas.instance = canvasInstance;
                    return canvasInstance;
                } else {
                    const pageId = global.__biliCacheData.getCurrentPageId();
                    let _readyCanvas = global.canvas[pageId][id];
                    if (_readyCanvas.instance) return _readyCanvas.instance;
                    let canvasInstance = new CanvasContext(id);
                    _readyCanvas.instance = canvasInstance;
                    return canvasInstance;
                }
            } else {
                return null;
            }
        }
    },
    canvasToTempFilePath() {
        let temp = Array.prototype.slice.apply(arguments);
        let checkRule = [
            {
                key: 'object',
                type: 'Object'
            }
        ];

        // api 参数类型校验
        const isOk = checkParam(temp, checkRule, {name: 'canvasToTempFilePath'});

        if (isOk) {
            if (global.canvas[temp[0]['canvasId']]) {
                global.canvas[temp[0]['canvasId']].queue.push({
                    class: 'canvas',
                    type: 'function',
                    name: 'toTempFilePath',
                    arguments: temp
                });
            } else {
                const pageId = global.__biliCacheData.getCurrentPageId();
                if (judgeEnv().isDowngrade) {
                    if (!global.canvas.callback) global.canvas.callback = {};
                    let tempCallback = {};
                    for (let key in temp[0]) {
                        if (key === 'success' || key === 'fail' || key === 'complete') {
                            let _tempId = shortId.generate();
                            tempCallback[key] = _tempId;
                            global.canvas.callback[_tempId] = temp[0][key];
                        }
                    }
                    global.canvas[pageId][temp[0]['canvasId']].queue.push({
                        class: 'canvas',
                        type: 'function',
                        callback: tempCallback,
                        callerType: 'return',
                        name: 'toTempFilePath',
                        arguments: temp
                    });
                    // 安卓降级方案
                    Service.postMessage(JSON.stringify({
                        type: 'canvas',
                        canvasId: temp[0]['canvasId'],
                        data: global.canvas[pageId][temp[0]['canvasId']].queue,
                        style: global.canvas[pageId][temp[0]['canvasId']].style
                    }), pageId);
                } else {
                    global.canvas[pageId][temp[0]['canvasId']].queue.push({
                        class: 'canvas',
                        type: 'function',
                        name: 'toTempFilePath',
                        arguments: temp
                    });
                    global.canvas[pageId][temp[0]['canvasId']].queue.forEach(x => {
                        consumptionQueue(temp[0]['canvasId'], x);
                    });
                }
                global.canvas[pageId][temp[0]['canvasId']].queue = [];
            }
        }
    },
    canvasPutImageData() {
        let temp = Array.prototype.slice.apply(arguments);
        let checkRule = [
            {
                key: 'object',
                type: 'Object'
            }
        ];

        // api 参数类型校验
        const isOk = checkParam(temp, checkRule, {name: 'canvasPutImageData'});

        if (isOk) {
            if (!global.canvas.callback) global.canvas.callback = {};
            let tempCallback = {};
            for (let key in temp[0]) {
                if (key === 'success' || key === 'fail' || key === 'complete') {
                    let _tempId = shortId.generate();
                    tempCallback[key] = _tempId;
                    global.canvas.callback[_tempId] = temp[0][key];
                }
            }

            if (global.canvas[temp[0]['canvasId']]) {
                global.canvas[temp[0]['canvasId']].queue.push({
                    class: 'ctx',
                    type: 'function',
                    name: 'putImageData',
                    callback: tempCallback,
                    callerType: 'return',
                    arguments: temp
                });
            } else {
                const pageId = global.__biliCacheData.getCurrentPageId();
                global.canvas[pageId][temp[0]['canvasId']].queue.push({
                    class: 'ctx',
                    type: 'function',
                    name: 'putImageData',
                    callback: tempCallback,
                    callerType: 'return',
                    arguments: temp
                });
                if (judgeEnv().isDowngrade) {
                    // 安卓降级方案
                    Service.postMessage(JSON.stringify({
                        type: 'canvas',
                        canvasId: temp[0]['canvasId'],
                        data: global.canvas[pageId][temp[0]['canvasId']].queue,
                        style: global.canvas[pageId][temp[0]['canvasId']].style
                    }), pageId);
                } else {
                    global.canvas[pageId][temp[0]['canvasId']].queue.forEach(x => {
                        consumptionQueue(temp[0]['canvasId'], x);
                    });
                }
                global.canvas[pageId][temp[0]['canvasId']].queue = [];
            }
        }
    },
    canvasGetImageData() {
        let temp = Array.prototype.slice.apply(arguments);
        let checkRule = [
            {
                key: 'object',
                type: 'Object'
            }
        ];

        // api 参数类型校验
        const isOk = checkParam(temp, checkRule, {name: 'canvasGetImageData'});

        if (isOk) {
            if (!global.canvas.callback) global.canvas.callback = {};
            let tempCallback = {};
            for (let key in temp[0]) {
                if (key === 'success' || key === 'fail' || key === 'complete') {
                    let _tempId = shortId.generate();
                    tempCallback[key] = _tempId;
                    global.canvas.callback[_tempId] = temp[0][key];
                }
            }

            if (global.canvas[temp[0]['canvasId']]) {
                global.canvas[temp[0]['canvasId']].queue.push({
                    class: 'ctx',
                    type: 'function',
                    name: 'getImageData',
                    callback: tempCallback,
                    callerType: 'return',
                    arguments: [temp[0]['x'], temp[0]['y'], temp[0]['width'], temp[0]['height']]
                });
            } else {
                const pageId = global.__biliCacheData.getCurrentPageId();
                global.canvas[pageId][temp[0]['canvasId']].queue.push({
                    class: 'ctx',
                    type: 'function',
                    name: 'getImageData',
                    callback: tempCallback,
                    callerType: 'return',
                    arguments: [temp[0]['x'], temp[0]['y'], temp[0]['width'], temp[0]['height']]
                });
                if (judgeEnv().isDowngrade) {
                    // 安卓降级方案
                    Service.postMessage(JSON.stringify({
                        type: 'canvas',
                        canvasId: temp[0]['canvasId'],
                        data: global.canvas[pageId][temp[0]['canvasId']].queue,
                        style: global.canvas[pageId][temp[0]['canvasId']].style
                    }), pageId);
                } else {
                    global.canvas[pageId][temp[0]['canvasId']].queue.forEach(x => {
                        consumptionQueue(temp[0]['canvasId'], x);
                    });
                }
                global.canvas[pageId][temp[0]['canvasId']].queue = [];
            }
        }
    }
};
