import { game } from "cc";
import { HTTP_SITE_ID, SERVER_LIST, GAME_VER } from "../setting/ServerConfig";
import { Tools } from "../tools/Tools";
import { app } from "../../app/app";
import { CHANNELDATA } from "../data/ChannelData";
import { EDITOR } from "cc/env";

var urls: any = {};                      // 当前请求地址集合
var reqparams: any = {};                 // 请求参数

/**
 * 登录token类，全局唯一
 */
export class LoginToken{
    private static instance: LoginToken | null = null;
    public access_token: string = "";
    public refresh_token: string = "";
    public appId: string = "";
    public appKey: string = "";
    private constructor(){}

    static get Instance(){
        if(LoginToken.instance == null){
            LoginToken.instance = new LoginToken();
        }
        return LoginToken.instance;
    }

    public setToken(access_token: string, refresh_token: string, appID: string, appKey: string){
        this.access_token = access_token;
        this.refresh_token = refresh_token;
        this.appId = appID
        this.appKey = appKey
    }
}

/** 当前保存的token */
export const LOGIN_TOKEN : LoginToken = LoginToken.Instance;

export enum HttpEvent {
    NO_NETWORK = "http_request_no_network",                  // 断网
    UNKNOWN_ERROR = "http_request_unknown_error",            // 未知错误
    TIMEOUT = "http_request_timout"                          // 请求超时
}


export class HttpRequest {
    /** 服务器地址 */
    public server: string = SERVER_LIST
    /** 请求超时时间 */
    public timeout: number = 10000;

    public lobbyUrl = ""

    public setUrl (url:string) {
        this.server = "http://" + url + "/"
    }

    /**
     * HTTP GET请求
     * 例：
     * 
     * Get
        var complete = function(response){
            LogWrap.log(response);
        }
        var error = function(response){
            LogWrap.log(response);
        }
        this.get(name, complete, error);
    */
    public get(name: string, completeCallback: Function, errorCallback?: Function) {
        this.sendRequest(name, null, false, completeCallback, errorCallback)
    }
    public getWithParams(name: string, params: any, completeCallback: Function, errorCallback?: Function) {
        this.sendRequest(name, params, false, completeCallback, errorCallback)
    }

    public getByArraybuffer(name: string, completeCallback: Function, errorCallback?: Function) {
        this.sendRequest(name, null, false, completeCallback, errorCallback, 'arraybuffer', false);
    }
    public getWithParamsByArraybuffer(name: string, params: any, completeCallback: Function, errorCallback?: Function) {
        this.sendRequest(name, params, false, completeCallback, errorCallback, 'arraybuffer', false);
    }

    /** 
     * HTTP POST请求
     * 例：
     *      
     * Post
        var param = '{"LoginCode":"donggang_dev","Password":"e10adc3949ba59abbe56e057f20f883e"}'
        var complete = function(response){
                var jsonData = JSON.parse(response);
                var data = JSON.parse(jsonData.Data);
            LogWrap.log(data.Id);
        }
        var error = function(response){
            LogWrap.log(response);
        }
        this.post(name, param, complete, error);
    */
    public post(name: string, params: any, completeCallback?: Function, errorCallback?: Function) {
        this.sendRequest(name, params, true, completeCallback, errorCallback);
    }

    /** 取消请求中的请求 */
    public abort(name: string) {
        var xhr = urls[this.server + name];
        if (xhr) {
            xhr.abort();
        }
    }

    /**
     * 获得字符串形式的参数
     */
    private getParamString(params: any) {
        var result = "";
        for (var name in params) {
            let data = params[name];
            if (data instanceof Object) {
                for (var key in data)
                    result += `${key}=${data[key]}&`;
            }
            else {
                result += `${name}=${data}&`;
            }
        }

        return result.substring(0, result.length - 1);
    }

    /** 
     * Http请求 
     * @param name(string)              请求地址
     * @param params(JSON)              请求参数
     * @param isPost(boolen)            是否为POST方式
     * @param callback(function)        请求成功回调
     * @param errorCallback(function)   请求失败回调
     * @param responseType(string)      响应类型
     */
    private async sendRequest(
    name: string,
    params: any,
    isPost: boolean,
    completeCallback?: Function,
    errorCallback?: Function,
    responseType?: string,
    isOpenTimeout = true,
    timeout: number = this.timeout
    ) {
        if (!name) {
            console.log("请求地址不能为空");
            return;
        }

        let url: string, newUrl: string, paramsStr: string;
        if (name.toLocaleLowerCase().indexOf("http") === 0) {
            url = name;
        } else {
            url = this.server + name;
        }

        if (params) {
            paramsStr = this.getParamString(params);
            if (url.indexOf("?") > -1)
                newUrl = url + "&" + encodeURIComponent(paramsStr);
            else
                newUrl = url + "?" + paramsStr;
        } else {
            newUrl = url;
        }

        if (urls[newUrl] != null && reqparams[newUrl] === paramsStr!) {
            console.log(`地址【${url}】已正在请求中，不能重复请求`);
            return;
        }

        const xhr = new XMLHttpRequest();
        urls[newUrl] = xhr;
        reqparams[newUrl] = paramsStr!;

        if (isPost) {
            xhr.open("POST", url);
        } else {
            xhr.open("GET", newUrl);
        }

        if (LOGIN_TOKEN.access_token !== "") {
            xhr.setRequestHeader("Authorization", "Bearer " + LOGIN_TOKEN.access_token);
        }
        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");

        // 加密设置
        const time = Math.floor(Date.now() / 1000);
        xhr.setRequestHeader("Lang", CHANNELDATA.lang);

        if (!params) params = {};
        let _params = params;
        _params.appId = LOGIN_TOKEN.appId;
        _params.nonceStr = Tools.getRandomStr(6);
        _params.timestamp = time;

        let sha256DDD: string;
        try {
            sha256DDD = await Tools.generateSignNative(_params, LOGIN_TOKEN.appKey);
        } catch (err) {
            console.error("生成签名失败:", err);
            this.deleteCache(newUrl);
            const data: any = { url, params, event: HttpEvent.UNKNOWN_ERROR };
            if (errorCallback) errorCallback(data);
            return; // 出错直接返回，避免继续执行
        }

        // xhr.setRequestHeader("appId", LOGIN_TOKEN.appId);
        // xhr.setRequestHeader("timestamp", _params.timestamp.toString());
        // xhr.setRequestHeader("signature", sha256DDD);
        // xhr.setRequestHeader("nonceStr", _params.nonceStr);
        // xhr.setRequestHeader("Site-Id", HTTP_SITE_ID);
        // const v = app.lib.storage.get("CURR_VERSION") || "100";
        // xhr.setRequestHeader("app-version-key", v.toString());
        // xhr.setRequestHeader("system-key", "android");
        // xhr.setRequestHeader("Client-Version", GAME_VER);
        xhr.setRequestHeader("X-Domain", LOGIN_TOKEN.appId);
        xhr.setRequestHeader("X-Locale", LOGIN_TOKEN.appKey);

        const data: any = { url, params };

        // 请求超时
        if (isOpenTimeout) {
            xhr.timeout = timeout;
            xhr.ontimeout = () => {
                this.deleteCache(newUrl);
                data.event = HttpEvent.TIMEOUT;
                if (errorCallback) errorCallback(data);
            };
        }

        xhr.onloadend = () => {
            if (xhr.status === 500) {
                this.deleteCache(newUrl);
                data.event = HttpEvent.NO_NETWORK;
                if (errorCallback) errorCallback(data);
            }
        };

        xhr.onerror = () => {
            this.deleteCache(newUrl);
            if (!errorCallback) return;
            if (xhr.readyState === 0 || xhr.readyState === 1 || xhr.status === 0) {
                data.event = HttpEvent.NO_NETWORK;
            } else {
                data.event = HttpEvent.UNKNOWN_ERROR;
            }
            errorCallback(data);
        };

        xhr.onreadystatechange = () => {
            if (xhr.readyState !== 4) return;
            this.deleteCache(newUrl);
            if (xhr.status === 200) {
                if (completeCallback) {
                    if (responseType === "arraybuffer") {
                        xhr.responseType = responseType;
                        completeCallback(xhr.response);
                    } else {
                        try {
                            const resp: any = JSON.parse(xhr.response);
                            if (resp.status === "success") {
                                const isDevelopment = EDITOR || (typeof window !== 'undefined' && (window.location.hostname.includes('localhost') || window.location.hostname.includes('127.0.0.1')));
                                if (isDevelopment) {
                                    console.log("data:", resp.data);
                                }
                                completeCallback(resp.data);
                            } else {
                                app.manager.ui.showToast(Tools.GetLocalized(resp.msg));
                                if (errorCallback) errorCallback(resp.data);
                            }
                            // if (Number(resp.code) === 200 || Number(resp.code) === 406) {
                            //     const isDevelopment = EDITOR || (typeof window !== 'undefined' && (window.location.hostname.includes('localhost') || window.location.hostname.includes('127.0.0.1')));
                            //     if (isDevelopment) {
                            //         console.log("data:", resp.data);
                            //     }
                            //     completeCallback(resp.data);
                            // } else {
                            //     app.manager.ui.showToast(Tools.GetLocalized(resp.msg));
                            //     if (errorCallback) errorCallback(resp.data);
                            // }
                        } catch (error) {
                            console.log("解析响应失败:", error);
                            if (errorCallback) errorCallback({ event: HttpEvent.UNKNOWN_ERROR });
                        }
                    }
                }
            }
        };

        if (!paramsStr) {
            xhr.send();
        } else {
            xhr.send(paramsStr!);
        }
    }

    private deleteCache(url: string) {
        delete urls[url];
        delete reqparams[url];
    }
}

export let httpRequest = new HttpRequest()