


import { EventDispatcher } from "../events/EventDispatcher";
import { createImage, getEnv } from "../utils";

/**
 * 加载器，不做缓存判断，所有的外部自行缓存，或者判断是否要进加载器
 * 仅仅是加载方法集成
 * 感觉没必要集成EventDispatcher
 * 加载方法都是回调方式
 * 无特殊要求的直接用GlobalLoader
 * 这里所有load方法参数都是（回调函数，路径）
 * 兼容了web和tb环境
 */
export class Loader extends EventDispatcher {
    /**
     * 记录原始数据，json和image，贴图在建立时会被缓存
     * 需要缓存的都用在回调里自行缓存，比如弄个RES
     */
    private caches = {};

    /**
     * 
     */
    constructor() {
        super();
        this._instanceType = "Loader";
    }

    /**
     * 加载图集
     * @param callback 
     * @param url 图集一般是png格式,传的是json,在callback自行拆分
     */
    loadSheet(callback: (success: boolean, sheet?: { json: any, img: HTMLImageElement }) => void, url: string) {
        let pngFile = url.substring(0, url.lastIndexOf('.')) + '.png';
        this.loadImage((suc, data) => {
            if (suc) {
                this.cache(pngFile, data);
                if (this.caches[url]) {
                    callback(true, { json: this.caches[url], img: data })
                    //已回调,释放置空
                    this.caches[url] = null;
                    this.caches[pngFile] = null;
                }
            } else {
                callback(false)
            }
        }, pngFile);


        this.loadJson((suc, data) => {
            if (suc) {
                this.cache(url, data);
                if (this.caches[pngFile]) {
                    callback(true, { json: data, img: this.caches[pngFile] });
                    //已回调,释放置空
                    this.caches[url] = null;
                    this.caches[pngFile] = null;
                }
            } else {
                callback(false)
            }
        }, url)
    }
    /**
     * 加载json文件
     * @param callback 
     * @param url 
     */
    loadJson(callback: (s: boolean, res: any) => void, url: string) {
        //@ts-ignore ,正式环境不能使用request，走downloadFile
        // my.request({
        //     url: url,
        //     dataType: "json",
        //     success: (res) => {
        //         callback(true, res.data)
        //     },
        //     fail: function (res) {
        //         // my.alert({
        //         //   title: JSON.stringify(res)
        //         // });
        //         callback(false, res)
        //     }
        // });
        if (getEnv() == "tb") {
            // this.tbLoad(callback, url, "utf8")
            this.tbLoad((s, res) => {
                callback(s, s ? JSON.parse(res) : res)//utf8返回的数字符串
            }, url, "utf8")
            return
        }
        this.loadRawWeb(callback, url, "json")
    }
    /**
     * 加载ArrayBuffer
     * @param callback 
     * @param url 
     */
    loadAB(callback: (s: boolean, res: ArrayBuffer) => void, url: string) {
        if (getEnv() == "tb") {
            this.tbLoad(callback, url, "ArrayBuffer")
        } else {
            this.loadRawWeb(callback, url, "arraybuffer")
        }
    }
    /**
     * web环境原生加载方式
     * @param callback 
     * @param url 
     * @param type 
     */
    loadRawWeb(
        callback: (s: boolean, res: any) => void,
        url: string,
        type: 'text' | 'json' | 'arraybuffer' = "json"
    ) {
        //每次都要new
        let _req;
        if (window["XMLHttpRequest"]) {
            _req = new XMLHttpRequest();
        } else if (window["ActiveXObject"]) {
            _req = new window["ActiveXObject"]();
        } else {
            alert("请升级至最新版本的浏览器")
        }
        if (_req != null) {
            _req.open("GET", url, true);
            _req.responseType = type;
            _req.send();
            _req.onreadystatechange = () => {
                if (_req.readyState == 4 && _req.status == 200) {
                    callback(true, _req.response)
                }
            };
            _req.onerror = (reason): void => {
                callback(false, reason)
            }
        }
    }
    /**
     * 加载图片
     * @param callback 
     * @param url 
     */
    loadImage(callback: (s: boolean, image?: HTMLImageElement) => void, url: string) {
        let img = createImage();
        //之前的劫持下
        // window["Image"] = function () {
        //     var image = canvas.createImage()
        //     return image
        // }
        // let img = new Image()
        img.onload = function () {
            callback(true, img);
        }
        img.onerror = function () {
            callback(false);
        }
        //坑爹中文，decodeURI一次是为了以防链接被encode过一次
        url = encodeURI(decodeURI(url))
        //除了base64的路径，其他都设置了跨域，其实有部分服务器不允许跨域，不能设置anonymous
        if (url.indexOf('data:') !== 0) img.crossOrigin = "anonymous";
        img.src = url;
    }
    /**
     * 淘宝加载方式
     * @param callback 
     * @param url 云存储链接cloud或者阿里系白名单域名
     */
    tbLoad(
        callback: (s: boolean, res?: any) => void,
        url: string,
        type: "utf8" | "ArrayBuffer" = "ArrayBuffer"
    ) {
        //类似这种地址"cloud://A8673B47AAA58993A24A6718E203B967//dice.svga"
        if (url.indexOf("cloud://") == 0) {
            this.getTbTempUrl((src) => {
                this.downloadReadFile(callback, src, type)
            }, url)
        } else {
            this.downloadReadFile(callback, url, type)
        }
    }

    /**
     * 淘宝小程序，获取云存储临时cdn地址
     * @param callback 
     * @param url 
     */
    private getTbTempUrl(callback: (src: string) => void, url) {
        //@ts-ignore
        const { cloud } = getApp();
        //获取临时地址
        cloud.file.getTempFileURL({ fileId: [url] }).then((urls) => {
            callback(urls[0].url.replace('-internal', ''))
        }).catch((err) => {
            console.error(err)
        })
    }

    /**
     * 
     * @param callback 
     * @param url 
     * @param type 指定的字符编码，不传表示以 ArrayBuffer 格式读取文件的二进制内容
     */
    private downloadReadFile(
        callback: (s: boolean, res?: any) => void,
        url: string,
        type: "utf8" | "ArrayBuffer" = "ArrayBuffer"
    ) {
        //@ts-ignore
        let tbMy = my;
        tbMy.downloadFile({
            url: url,
            success(res) {
                var i = res.apFilePath;//临时地址是否有必要缓存下，如果读不到再考虑下载。
                tbMy.getFileSystemManager().readFile({
                    filePath: i,
                    encoding: type === "ArrayBuffer" ? "" : type,//不加表示加载的是ArrayBuffer
                    success: function (r) {
                        callback(true, r.data)//注意是r.data
                        // actions.load_viaProto(r.data, cb, failure);
                    },
                    fail: function (res) {
                        callback(false, res)
                    }
                })
            },
            fail(res) {
                callback(false, res)
            },
        });
    }

    private cache(name: string, data: any) {
        if (this.caches[name]) {
            console.log("覆盖原先数据：" + name);
        }
        this.caches[name] = data
    }


}
/**
 * 一个全局加载器实例
 */
export const GlobalLoader = new Loader();
  //https://yun.duiba.com.cn/db_games/activity/yilian0726/1565580040/resource/result/resultAlta1.json
    //"https://yun.duiba.com.cn/db_games/activity/etc/optionImages/%E5%8D%8E%E4%B8%BAP30.jpg"