Engine.JSONRequest = class
{

    constructor()
    {
    	this.Variables = {};
    	this.baseURL = EngineSettings.WebRoot + "post.php?";
    	this.callback = null;
    	this.lastURL = "";
    	this.JSONResult = {};
        this.requestStartTime = 0;
        this.lastProgressTime = 0;
    	this.retryTimes = 2;
        this.showErrors = true;
        this.wwwRequest = null;

    	this.timeoutTime = 15;
        this.defaultTimeoutTime = 15;
    	this.webRequestReturnedText = "";
    }

    getJSON() { return this.JSONResult; }

    makeBuiltRequest(callback, loadingMessage, messageDelay)
    {
        if (loadingMessage === undefined) loadingMessage = "";
        if (messageDelay === undefined) messageDelay = 0;

        this.timeoutTime = this.defaultTimeoutTime;
        this.requestStartTime = Engine.Utils.getTimer();
        this.lastProgressTime = Engine.Utils.getTimer();
        this.retryTimes = 2;
        this.callback = callback;

        this.makeBuiltRequestInternal();

        Engine.EnterFrameManagerInstance.add(this, this.checkComplete);

        this.loadingBox = null;
        if (loadingMessage != "") this.loadingBox = Engine.DialogManagerInstance.showLoadingTextBox(loadingMessage, messageDelay, true, false);
    }

    makeBuiltRequestInternal()
    {
        if (this.wwwRequest != null) this.wwwRequest.abort();

        var urlParams = "";

        this.Variables["timestamp"] = "" + Engine.JSONRequest.calculateTimeStamp();
        if (!this.Variables.containsKey("request_id")) this.Variables["request_id"] = "" + Engine.JSONRequest.getIncrementingID();

        var defaults = EngineSettings.JSONDefaults;
        for(var key in defaults)
        {
            this.Variables[key] = defaults[key];
        }

        this.Variables["network_id"] =  "" + GameSettings.platform;

        for(var key in this.Variables)
        {
            urlParams += encodeURIComponent(key) + "=" + encodeURIComponent(this.Variables[key]) + "&";
        }

        if (!this.Variables["call"] || this.Variables["call"] != "saveuserdetails")
        {
            this.wwwRequest = new Engine.WebRequest();
            this.wwwRequest.onProgress = (request, downloaded, downloadLength) => this.onDownloadProgress(request, downloaded, downloadLength);
            this.wwwRequest.makeRequest(this.baseURL + urlParams, () => { this.onRequestFinished(this.wwwRequest); } );
        }
        else
        {
            this.wwwRequest = new Engine.WebRequest();
            this.wwwRequest.onProgress = (request, downloaded, downloadLength) => this.onDownloadProgress(request, downloaded, downloadLength);
            this.wwwRequest.makePostRequest(this.baseURL, urlParams, () => { this.onRequestFinished(this.wwwRequest); } );
        }

        Debug.Log("JSON Request: " + this.baseURL + urlParams);
        this.lastParams = urlParams;
    }

    onDownloadProgress(originalRequest, downloaded, downloadLength)
    {
        var progressPercent = (downloaded / downloadLength) * 100;
        //if (this.progressCallback != null) progressCallback(new WebRequestProgressInfo(downloaded, downloadLength));
        //Debug.Log("Progress: " + progressPercent);
        this.lastProgressTime = Engine.Utils.getTimer();
    }

    onRequestFinished(webrequest)
    {
        this.JSONResult = webrequest.data;
        this.completeRequest();
    }

    retry()
    {
        this.requestStartTime = Engine.Utils.getTimer();
        this.lastProgressTime = Engine.Utils.getTimer();

        this.retryTimes--;
        this.timeoutTime *= 2;

        if (this.loadingBox != null) this.loadingBox.show("Retrying Request");
        this.makeBuiltRequestInternal();
    }

    checkComplete(timeElapsed)
    {
        //Debug.Log("" + this.Variables["request_id"] + " - " +  this.requestTime);
        //this.requestTime += timeElapsed;
        var totalRequestTime = (Engine.Utils.getTimer() - this.requestStartTime) / 1000;
        var timeSinceProgress = (Engine.Utils.getTimer() - this.lastProgressTime) / 1000;

        if (!this.complete && timeSinceProgress > this.timeoutTime)
        {
            if (this.retryTimes > 0)
            {
                this.retry();
            }
            else if (this.showErrors)
            {
                this.JSONResult["failure_reason"] = "Request Timed Out.\nCheck your Internet Connection and Retry.";
                this.completeRequest();
            }
        }
    }

    completeRequest()
    {
        Engine.EnterFrameManagerInstance.remove(this);
        if (this.loadingBox != null) this.loadingBox.hide();
        if (this.callback != null) this.callback(this);
    }


    static setTimeStamp(serverValue)
    {
        if (!JSONRequestStatics.TimeStampSet)
        {
            var now = Math.floor(new Date().getTime() / 1000);
            JSONRequestStatics.TimeStampSet = true;
            JSONRequestStatics.TimeStampStart = now;
            JSONRequestStatics.TimeStampDelta = serverValue;
        }
    }

    static calculateTimeStamp()
    {
        var now = Math.floor(new Date().getTime() / 1000);
        var diff = Math.floor(now - JSONRequestStatics.TimeStampStart);
        return diff + JSONRequestStatics.TimeStampDelta;
    }

    static getIncrementingID()
    {
        if (!JSONRequestStatics.isIdSet)
        {
            JSONRequestStatics.uniqueId = Math.floor(Math.random() * 2147483647);
            JSONRequestStatics.isIdSet = true;
        }
        return JSONRequestStatics.uniqueId++;
    }
    static resetIncrementingID()
    {
        JSONRequestStatics.uniqueId = Math.floor(Math.random() * 2147483647);
        JSONRequestStatics.isIdSet = true;
    }
}

var JSONRequestStatics = {
    uniqueId:0,
    isIdSet: false,
    TimeStampSet: false,
    TimeStampStart: 0,
    TimeStampDelta: 0
};
