
class AsyncTask {

    constructor(method, args)
    {
        this._method = method;
        this._args = args;
    }

    execute()
    {
        if (!(this._method in Statistics))
            throw `${this._method} is not a valid method of Statistics`;

        AsyncTask._asyncMessageId++;

        var startTime = Date.now();
        var method = this._method;
        var args = this._args;
        return new Promise(function (resolve, reject) {
            AsyncTaskWorker.waitForAvailableWorker(function (worker) {
                worker.sendTask({id: AsyncTask._asyncMessageId, method: method, args: args}).then(function (data) {
                    var startLatency = data.workerStartTime - startTime;
                    var totalTime = Date.now() - startTime;
                    var callback = data.status == 'resolve' ? resolve : reject;
                    callback({result: data.result, workerId: worker.id(), startLatency: startLatency, totalTime: totalTime, workerTime: data.workerTime});
                });
            });
        });
    }

}

AsyncTask._asyncMessageId = 0;

class AsyncTaskWorker {

    // Takes a callback instead of returning a promise because a worker can become unavailable before the end of the current microtask.
    static waitForAvailableWorker(callback)
    {
        var worker = this._makeWorkerEventuallyAvailable();
        if (worker)
            callback(worker);
        this._queue.push(callback);
    }

    static _makeWorkerEventuallyAvailable()
    {
        var worker = this._findAvailableWorker();
        if (worker)
            return worker;

        var canStartMoreWorker = this._workerSet.size < this._maxWorkerCount;
        if (!canStartMoreWorker)
            return null;

        if (this._latestStartTime > Date.now() - 50) {
            setTimeout(function () {
                var worker = AsyncTaskWorker._findAvailableWorker();
                if (worker)
                    AsyncTaskWorker._queue.pop()(worker);
            }, 50);
            return null;
        }
        return new AsyncTaskWorker;
    }

    static _findAvailableWorker()
    {
        for (var worker of this._workerSet) {
            if (!worker._currentTaskId)
                return worker;
        }
        return null;
    }

    constructor()
    {
        this._webWorker = new Worker('async-task.js');
        this._webWorker.onmessage = this._didRecieveMessage.bind(this);
        this._id = AsyncTaskWorker._workerId;
        this._startTime = Date.now();
        this._currentTaskId = null;
        this._callback = null;

        AsyncTaskWorker._latestStartTime = this._startTime;
        AsyncTaskWorker._workerId++;
        AsyncTaskWorker._workerSet.add(this);
    }

    id() { return this._id; }

    sendTask(task)
    {
        console.assert(!this._currentTaskId);
        console.assert(task.id);
        var self = this;
        this._currentTaskId = task.id;
        return new Promise(function (resolve) {
            self._webWorker.postMessage(task);
            self._callback = resolve;
        });
    }

    _didRecieveMessage(event)
    {
        var callback = this._callback;

        console.assert(this._currentTaskId);
        this._currentTaskId = null;
        this._callback = null;

        if (AsyncTaskWorker._queue.length)
            AsyncTaskWorker._queue.pop()(this);
        else {
            var self = this;
            setTimeout(function () {
                if (self._currentTaskId == null)
                    AsyncTaskWorker._workerSet.delete(self);
            }, 1000);
        }

        callback(event.data);
    }

    static workerDidRecieveMessage(event)
    {
        var data = event.data;
        var id = data.id;
        var method = Statistics[data.method];
        var startTime = Date.now();
        try {
            var returnValue = method.apply(Statistics, data.args);
            postMessage({'id': id, 'status': 'resolve', 'result': returnValue, 'workerStartTime': startTime, 'workerTime': Date.now() - startTime});
        } catch (error) {
            postMessage({'id': id, 'status': 'reject', 'result': error.toString(), 'workerStartTime': startTime, 'workerTime': Date.now() - startTime});
            throw error;
        }
    }
}

AsyncTaskWorker._maxWorkerCount = typeof navigator != 'undefined' && 'hardwareConcurrency' in navigator ? Math.max(1, navigator.hardwareConcurrency - 1) : 1;
AsyncTaskWorker._workerSet = new Set;
AsyncTaskWorker._queue = [];
AsyncTaskWorker._workerId = 1;
AsyncTaskWorker._latestStartTime = 0;

if (typeof module == 'undefined' && typeof window == 'undefined' && typeof importScripts != 'undefined') { // Inside a worker
    importScripts('/shared/statistics.js');
    onmessage = AsyncTaskWorker.workerDidRecieveMessage.bind(AsyncTaskWorker);
}
