/**
 * 记录的一些方法和设置
 */

import { BLEND_MODES } from "../const";
import { RENDERER_TYPE } from "../const";
import { Rectangle, Matrix } from "../math";
import CanvasRenderer from "../renderers/CanvasRenderer";
import { DisplayObject } from "../display/DisplayObject";
import RenderTexture from "../texture/RenderTexture";
import { mapPremultipliedBlendModes } from "./mapPremultipliedBlendModes";


export * from './twiddle';
export { default as toDisplayDataURL } from "./toDisplayDataURL";
export { default as determineCrossOrigin } from './determineCrossOrigin';
export * from "./getTintedTexture";
export * from "./mapWebGLBlendModes";
export * from "./mapCanvasBlendModes";

export * from "./DrawAllToCanvas";

export const premultiplyBlendMode = mapPremultipliedBlendModes();

let nextUid = 0;

/**
 * 获得唯一id
 * @function uid
 * @return {number} 唯一的id
 */
export function uid(): number {
    return ++nextUid;
}

/**
 * 各种使用需要的canvas
 * 比如取canvas上下文创建对象，渐变色等
 * 像素碰撞检测时
 * 
 */
export const backupCanvas: HTMLCanvasElement = document.createElement("canvas")
/**
 * 创建渐变色
 * @param points 
 * @param colors 
 */
export function getGradientColor(points: any, colors: any): any {
    let colorObj: any;
    let ctx = backupCanvas.getContext("2d");
    if (points.length == 4) {
        colorObj = ctx.createLinearGradient(points[0], points[1], points[2], points[3]);
    } else {
        colorObj = ctx.createRadialGradient(points[0], points[1], 0, points[2], points[3], points[4]);
    }
    for (let i = 0, l = colors.length; i < l; i++) {
        colorObj.addColorStop(colors[i][0], getRGBA(colors[i][1], colors[i][2]));
    }
    return colorObj;
}
/**
 * 创建重复纹理
 * @param image 
 */
export function getCanvasBitmapStyle(image: any): any {
    let ctx = backupCanvas.getContext("2d");
    return ctx.createPattern(image, "repeat");
}
/**
 * 十六进制颜色转rgb数组
 * @function hex2rgb
 * @param {number} hex -转换的十六进制颜色
 * @param  {number[]} [out=[]] 输出数组，
 * @return {number[]} [R, G, B]颜色 每项范围0到1
 */
export function hex2rgb(hex: number, out?: number[] | Float32Array): number[] | Float32Array {
    out = out || [];
    out[0] = ((hex >> 16) & 0xFF) / 255;
    out[1] = ((hex >> 8) & 0xFF) / 255;
    out[2] = (hex & 0xFF) / 255;
    return out;
}

/**
 * 十六进制颜色转字符串
 * 0xffffff转"#ffffff"
 * @function hex2string
 * @param {number} hex - 转换的十六进制颜色
 * @return {string} 输出的字符串颜色.
 */
export function hex2string(hex: any): string {
    hex = hex.toString(16);
    hex = '000000'.substr(0, 6 - hex.length) + hex;
    return `#${hex}`;
}

/**
 * 字符串颜色转十六进制
 * "#ffffff"或"0xffffff"转0xffffff
 * @param {string} string 转换的字符串颜色
 * @return {number} 输出的颜色数值
 */
export function string2hex(string: string) {
    if (string.indexOf("#") == 0) {
        string = string.replace("#", "0x")
    }
    return parseInt(string)
}

/**
 * 数组[R, G, B]转换为十六进制数值
 * rgb范围时0到1，和着色器中的一致
 * @function rgb2hex
 * @param {number[]} rgb -数组
 * @return {number} 十六进制颜色
 */
export function rgb2hex(rgb: number[]): number {
    return (((rgb[0] * 255) << 16) + ((rgb[1] * 255) << 8) + (rgb[2] * 255 | 0));
}

/**
 * 通过字符串颜色值和一个透明度值生成RGBA值
 * 用于canvas的api，
 * @method getRGBA
 * @param {string} color 字符串的颜色值,如:#33ffee
 * @param {number} alpha 0-1区间的一个数据 0完全透明 1完全不透明
 * @return {string}
 */
export function getRGBA(color: string, alpha: number): string {
    if (color.indexOf("0x") == 0) {
        color = color.replace("0x", "#");
    }
    //暂没考虑#ff这种
    if (color.length < 7) {
        color = "#000000";
    }
    if (alpha != 1) {
        let r = parseInt("0x" + color.substr(1, 2));
        let g = parseInt("0x" + color.substr(3, 2));
        let b = parseInt("0x" + color.substr(5, 2));
        color = "rgba(" + r + "," + g + "," + b + "," + alpha + ")";
    }
    return color;
}

/**
 * 输入框ios兼容，如果加过输入框，加
 */
export function inputFeildIosEnable() {
    var u = navigator.userAgent, app = navigator.appVersion
    var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
    if (isIOS) {
        setTimeout(() => {
            window["$"]("input").blur(function () {
                if (isIOS) {
                    blurAdjust()
                    // alert("1231321233")
                }
            });
        }, 50)
    }
    // 解决苹果不回弹页面
    function blurAdjust() {
        setTimeout(() => {
            // alert("1231321233")
            if (document.activeElement.tagName == 'INPUT' || document.activeElement.tagName == 'TEXTAREA') {
                return
            }
            let result = 'pc';
            if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) { //判断iPhone|iPad|iPod|iOS
                result = 'ios'
            } else if (/(Android)/i.test(navigator.userAgent)) {  //判断Android
                result = 'android'
            }
            if (result = 'ios') {
                document.activeElement["scrollIntoViewIfNeeded"](true);
            }
        }, 100)
    }
}


/**
 * Regexp for data URI.
 * Based on: {@link https://github.com/ragingwind/data-uri-regex}
 *
 * @static
 * @constant
 * @example data:image/png;base64
 */
const DATA_URI: any = /^\s*data:(?:([\w-]+)\/([\w+.-]+))?(?:;charset=([\w-]+))?(?:;(base64))?,(.*)/i;
/**
 * Split a data URI into components. Returns undefined if
 * parameter `dataUri` is not a valid data URI.
 *
 * @memberof utils
 * @function decomposeDataUri
 * @param {string} dataUri - the data URI to check
 * @return {utils~DecomposedDataUri|undefined} The decomposed data uri or undefined
 */
export function decomposeDataUri(dataUri) {
    const dataUriMatch = DATA_URI.exec(dataUri);
    if (dataUriMatch) {
        return {
            mediaType: dataUriMatch[1] ? dataUriMatch[1].toLowerCase() : undefined,
            subType: dataUriMatch[2] ? dataUriMatch[2].toLowerCase() : undefined,
            charset: dataUriMatch[3] ? dataUriMatch[3].toLowerCase() : undefined,
            encoding: dataUriMatch[4] ? dataUriMatch[4].toLowerCase() : undefined,
            data: dataUriMatch[5],
        };
    }
    return undefined;
}

/**
 * Regexp for image type by extension.
 *
 * @static
 * @constant
 * @type {RegExp|string}
 * @example `image.png`
 */
const URL_FILE_EXTENSION: any = /\.(\w{3,4})(?:$|\?|#)/i;
/**
 * 根据图片路径获取图片扩展名
 * @memberof utils
 * @function getUrlFileExtension
 * @param {string} url - the image path
 * @return {string|undefined} image extension
 */
export function getUrlFileExtension(url) {
    const extension = URL_FILE_EXTENSION.exec(url);
    if (extension) {
        return extension[1].toLowerCase();
    }
    return undefined;
}

/**
 * 获取正负号标记
 * 0 +1 -1
 * @memberof utils
 * @function sign
 * @param {number} n 
 * @returns {number} 
 */
export function sign(n: number): number {
    if (n === 0) return 0;
    return n < 0 ? -1 : 1;
}

/**
 * 预乘十六进制颜色与透明度
 * 着色器只需传一个参数
 * @param tint 
 * @param alpha 
 */
export function premultiplyTint(tint: number, alpha: number): number {
    if (alpha === 1.0) {
        return (alpha * 255 << 24) + tint;
    }
    if (alpha === 0.0) {
        return 0;
    }
    var R = ((tint >> 16) & 0xFF);
    var G = ((tint >> 8) & 0xFF);
    var B = (tint & 0xFF);

    R = ((R * alpha) + 0.5) | 0;
    G = ((G * alpha) + 0.5) | 0;
    B = ((B * alpha) + 0.5) | 0;

    return (alpha * 255 << 24) + (R << 16) + (G << 8) + B;
}
/**
 * 贴图缓存 
 * 对于链接网络图片，直接以url作为key，自动缓存
 * 对于图集，直接以小图命名作为key（所以避免重复名字，不是同一张图集里的命名也不能一致，否则覆盖）
 * 不自动缓存base64图片
 * @private
 */
export const TextureCache = Object.create(null);

/**
 * 基础贴图缓存
 * 基本不会直接用，不缓存base64
 * @private
 */
export const BaseTextureCache = Object.create(null);

/**
 * 记录TextureSheet，便于帧动画贴图数据查找
 */
export const TextureSheetCache = Object.create(null);

/**
 * 销毁所有缓存的纹理和基础纹理
 * @function destroyTextureCache
 */
export function destroyTextureCache() {
    let key;

    for (key in TextureCache) {
        TextureCache[key].destroy();
    }
    for (key in BaseTextureCache) {
        BaseTextureCache[key].destroy();
    }
}

/**
 * 移除所有缓存的纹理和基础纹理，但不销毁
 * @function clearTextureCache
 */
export function clearTextureCache() {
    let key;

    for (key in TextureCache) {
        delete TextureCache[key];
    }
    for (key in BaseTextureCache) {
        delete BaseTextureCache[key];
    }
}

/**
 * 全局属性记录
 * 除了引擎内部修改赋值，外部仅供读取
 */
export const GlobalPro = {
    /**
     * 舞台渲染类型，
     */
    stageRenderType: RENDERER_TYPE.WEBGL,
    /**
     * 实际渲染分辨率
     */
    dpi: 1,
    /**
     * 图集间隙
     */
    padding: 2,


}

/**
 * 判断是否支持webgl
 * @function isWebGLSupported
 * @return {boolean}
 */
export function isWebGLSupported(): boolean {
    const contextOptions = { stencil: true, failIfMajorPerformanceCaveat: true };
    try {
        if (!window["WebGLRenderingContext"]) {
            return false;
        }
        const canvas = document.createElement('canvas');
        let gl = canvas.getContext('webgl', contextOptions) || canvas.getContext('experimental-webgl', contextOptions);
        const success = !!(gl && gl["getContextAttributes"]().stencil);
        if (gl) {
            const loseContext = gl["getExtension"]('WEBGL_lose_context');
            if (loseContext) {
                loseContext.loseContext();
            }
        }
        gl = null;
        return success;
    }
    catch (e) {
        return false;
    }
}

/**
 * 从数组中移除元素
 * @param arr 原数组
 * @param startIdx 开始下标
 * @param removeCount 移除数量
 */
export function removeItems(arr: Array<any>, startIdx: number, removeCount: number) {
    var i, length = arr.length

    if (startIdx >= length || removeCount === 0) {
        return
    }
    removeCount = (startIdx + removeCount > length ? length - startIdx : removeCount)

    var len = length - removeCount

    for (i = startIdx; i < len; ++i) {
        arr[i] = arr[i + removeCount]
    }
    arr.length = len
}


