import Stage = Laya.Stage;
import WebGL = Laya.WebGL;
import Event = Laya.Event;
import HttpRequest = Laya.HttpRequest;
import Text = Laya.Text;
import Browser = Laya.Browser;
import { Main } from "../../Main";
import { PlayerAccount } from "./PlayerAccount";
import WxApi from "../../WXSDK/wxsdk";

const PROTOCOL_URL:string = "https://fallraceapi.94xj.net/";

export class PROTOCOLS {

    public static Login				= "user/login";				// not token

    public static game                 = "game/start";
    public static end                  = "game/play";

    public static Sign              = "sign/sign";

    public static EquipHero           = "theme/equipHero";
    public static BuyHero             = "theme/buyHero";
    public static EquipHat           = "theme/equipHat";
    public static BuyHat             = "theme/buyHat";
    public static BuyDance             = "theme/buyDance";
    public static EquipDance           = "theme/equipDance";

    public static share                = "fission/share";
    public static vd                   = "fission/vd";
    public static revival              = "game/revival";
    public static fissionhat           = "fission/hat";
    public static fissionhero          = "fission/hero";
    public static fissiondance          = "fission/dance";
    public static treasure       = "treasure/click";

    public static Config            = "config/table";
};

export class NetworkManager
{
    private static instance:NetworkManager;
    public static get Instance()
    {
        if(NetworkManager.instance)
        {
            return NetworkManager.instance;
        }
        else
        {
            return new NetworkManager();
        }
    }

    constructor()
    {
        NetworkManager.instance = this;
    }


    //#region 登入
    /******************************* login *****************************/
    public login(progresscb:Laya.Handler, completecb:Laya.Handler, errorcb:Laya.Handler): void
    {
        var userInfor = PlayerAccount.CurrentAccount;
        var ver = Main.Ver;

        let args:string = `code=${userInfor.Code}&nickname=${userInfor.NickName}&avatar=${userInfor.Avatar}&gender=${userInfor.Gender}&country=${userInfor.Country}&province=${userInfor.Province}&city=${userInfor.City}& device=${userInfor.Device}$&share_id=${userInfor.ShareId}&scene=${userInfor.Scene}&v=${ver}`;
        
        let httpRequest = new HttpRequest();
        httpRequest.once(Event.PROGRESS, this, this.onHttpRequestProgress, [progresscb, httpRequest]);
        httpRequest.once(Event.COMPLETE, this, this.onLoginRequestComplete, [completecb, httpRequest]);
        httpRequest.once(Event.ERROR, this, this.onHttpRequestError, [errorcb, httpRequest]);
        httpRequest.send(PROTOCOL_URL+PROTOCOLS.Login , args, "post", "text");
    }

    private onHttpRequestProgress(progresscb:Laya.Handler,httpRequest:HttpRequest)
    {
        if(progresscb)
        {
            console.log("HttpRequestProgress:...");
            progresscb.run();
        }
    }

    private onLoginRequestComplete(completecb:Laya.Handler,httpRequest:HttpRequest)
    {
        //console.log("登录数据：", httpRequest.data);
        let data: JSON = JSON.parse(httpRequest.data);
			if (data["code"] != "0") {
				console.log("登录异常错误！错误信息：", httpRequest.data);
				//completecb.runWith(data);
				return;
            }
            PlayerAccount.ServerTime = data["t"];
            PlayerAccount.CurrentAccount.SetAccountData(data);
			completecb.runWith(data);
    }

    private onHttpRequestError(errorcb:Laya.Handler,httpRequest:HttpRequest)
    {
        if (errorcb != null) {
            errorcb.runWith(httpRequest);
        }
        //WxApi.ShowLoading("连接网络失败...");
        //Laya.timer.once(5000,this,()=>{WxApi.HideLoading();})
        console.log("Error! Http request error..." + httpRequest.data);
    }
    //#endregion
    

    /*
    * 通用Http Post协议发送
    * protocol 		对应“PROTOCOLS”字典中协议名称
    * hasToken		是否使用token，目前只有login协议不需要token，其他都需要token，所以此处自动组合
    * param			参数列表，key是字段名，val是值，值需要先转string
    * completecb	协议发送成功回调函数
    * errorcb		协议发送失败回调函数
    * return		返回值为void
    */
    public HttpPostRequest(protocol:string, param:Array<{[key:string]:string}>, completecb:Laya.Handler, errorcb:Laya.Handler, hasToken:boolean = true):void 
    {
        let args:string = "";
        let url:string = PROTOCOL_URL + protocol;
        // chechk add token
        var account = PlayerAccount.CurrentAccount;
        var accountdata = account.CurAccountData;
        if (hasToken == true) 
        {
            args = `token=${accountdata.m_token}&`;
        }

        WxApi.ShowLoading("连接网络中...");
        if (protocol == PROTOCOLS.game || protocol == PROTOCOLS.end || protocol == PROTOCOLS.fissionhat || protocol == PROTOCOLS.fissionhero || protocol == PROTOCOLS.fissiondance || protocol == PROTOCOLS.vd)
        {
            let str  = "abcdefghijkimnopqrstuvwxyz0123456789";
            let code = "{";
            let mask = "";
            for (let i = 0; i < 4; i++) 
            {
                mask += str[Math.floor( Math.random() * 100) % str.length];
            }
            for (let i = 0; i < param.length; i++)
            {
                for (let key in param[i]) 
                {
                    code += `\"${key}\":\"${param[i][key]}\"`;
                }
                if (i < param.length - 1) 
                {
                    code += ",";
                }
                else
                {
                    code += "}";
                }
            }
            args += "_r=" + mask + this.base64Encode(code);
        }
        else
        {
            if (param != null) 
            {
                for (let i = 0; i < param.length; i++) 
                {
                    for (let key in param[i]) 
                    {
                        let val:string = param[i][key];
                        args += `${key}=${val}`;
                        if (i < param.length - 1) 
                        {
                            args += "&";
                        }
                    }
                }
            }
        }
        let httpRequest = new HttpRequest();
        httpRequest.once(Event.COMPLETE, this, this.onHttpRequestComplete, [completecb, errorcb, httpRequest]);
        httpRequest.once(Event.ERROR, this, this.onHttpRequestError, [errorcb, httpRequest]);
        httpRequest.send(url, args, "post", "text");
    }
        
    private onHttpRequestComplete(succeedcb:Laya.Handler, failurecb:Laya.Handler, httpRequest:HttpRequest):void 
    {
        WxApi.HideLoading();
        let data: JSON = JSON.parse(httpRequest.data);
        if (data["code"] == 0)
        {
            PlayerAccount.CurrentAccount.SetAccountData(data);
            if (succeedcb != null) 
            {
                //console.log("上传成功回调方法 " + httpRequest.data);
                succeedcb.runWith(data);
            }
        }
        else
        {
            if (failurecb != null) 
            {
                failurecb.runWith(data);
            }

            Laya.timer.once(5000,this,()=>{WxApi.HideLoading();})
            console.log("Error! Http request complete error, code: " + data["code"] + " message: " + data["message"]);
        }
    }

    private base64Encode (str):string {
        var c1, c2, c3;
        var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        var i = 0, len = str.length, string = '';
        while (i < len) {
          c1 = str.charCodeAt(i++) & 0xff;
          if (i == len) {
            string += base64EncodeChars.charAt(c1 >> 2);
            string += base64EncodeChars.charAt((c1 & 0x3) << 4);
            string += "==";
            break;
          }
          c2 = str.charCodeAt(i++);
          if (i == len) {
            string += base64EncodeChars.charAt(c1 >> 2);
            string += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
            string += base64EncodeChars.charAt((c2 & 0xF) << 2);
            string += "=";
            break;
          }
          c3 = str.charCodeAt(i++);
          string += base64EncodeChars.charAt(c1 >> 2);
          string += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
          string += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
          string += base64EncodeChars.charAt(c3 & 0x3F)
        }
        return string;
      }
}