"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.LoaderTaskManager = void 0;
var dom_utils_1 = require("../shared/dom-utils");
var lodash_1 = require("../shared/lodash");
var custom_1 = require("../custom");
var interface_1 = require("../interface");
var interface_2 = require("./interface");
var utils_1 = require("./utils");
var LoaderTaskManager = (function (_super) {
    __extends(LoaderTaskManager, _super);
    function LoaderTaskManager(type, uber) {
        var _this = _super.call(this) || this;
        _this._working = false;
        _this._reserved = 0;
        _this._type = type;
        _this._stack = [];
        _this._wipList = [];
        _this._uber = uber;
        return _this;
    }
    Object.defineProperty(LoaderTaskManager.prototype, "working", {
        get: function () {
            return this._working;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(LoaderTaskManager.prototype, "type", {
        get: function () {
            return this._type;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(LoaderTaskManager.prototype, "debug", {
        get: function () {
            return this._uber.debug;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(LoaderTaskManager.prototype, "options", {
        get: function () {
            return {
                debug: this.debug,
                retry: this._uber.getOption('retry'),
            };
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(LoaderTaskManager.prototype, "reserved", {
        get: function () {
            return this._reserved > 0;
        },
        enumerable: false,
        configurable: true
    });
    LoaderTaskManager.prototype._reserveJobs = function () {
        this._reserved += 1;
    };
    LoaderTaskManager.prototype._resolveJobs = function () {
        if (this.reserved) {
            this._reserved -= 1;
            if (this._stack.length) {
                this.start();
            }
        }
    };
    LoaderTaskManager.prototype._newWipItem = function (item) {
        if ((0, lodash_1.isNil)(item))
            return null;
        this._wipList.push(item);
        return item;
    };
    LoaderTaskManager.prototype._resolveWipItem = function (item) {
        (0, lodash_1.remove)(this._wipList, function (o) { return o.id === item.id; });
        return item;
    };
    LoaderTaskManager.prototype._checkIgnoreItem = function (item) {
        return this.type === interface_2.LoaderTaskType.LOAD ? item.loaded : !item.loaded;
    };
    LoaderTaskManager.prototype.add = function (item, immediatly) {
        if (immediatly === void 0) { immediatly = false; }
        if (this._checkIgnoreItem(item)) {
            if (this.debug) {
                console.warn("\"".concat(item.alias, "\" is already ").concat(this.type, "ed"));
            }
            return null;
        }
        if (this.exists(item)) {
            if (this.debug) {
                console.warn("\"".concat(item.alias, "\" is already added to the tasks"));
            }
            return null;
        }
        this._stack.push(item);
        if (immediatly)
            this.start();
        return item;
    };
    LoaderTaskManager.prototype.exists = function (item) {
        var target = (0, lodash_1.find)(this._stack, { id: item.id });
        if ((0, lodash_1.isNil)(target) && this._wipList.length) {
            target = (0, lodash_1.find)(this._wipList, { id: item.id });
        }
        return !(0, lodash_1.isNil)(target);
    };
    LoaderTaskManager.prototype._start = function () {
        var _this = this;
        if (this.working) {
            this._reserveJobs();
            return;
        }
        this._working = true;
        var startTime = (0, lodash_1.now)();
        var asyncTasks = [];
        var item;
        var _loop_1 = function () {
            item = this_1._newWipItem(this_1._stack.shift());
            if ((0, lodash_1.isNil)(item) || this_1._checkIgnoreItem(item))
                return "continue";
            if (this_1.debug) {
                console.log("%c[".concat(this_1.type, ".start] ").concat(item.alias), 'color:royalblue');
            }
            var eventData = { target: item };
            this_1.emit(interface_1.LoaderEventName.LOAD, eventData);
            var eventList = (0, utils_1.getTaskEventsByType)(this_1.type);
            var task = new Promise(function (resolve) {
                eventList.forEach(function (event) {
                    item.once(event, function (evt) {
                        _this.emit(event, eventData);
                        if ((0, utils_1.isResolveTaskEvent)(event)) {
                            _this._resolveWipItem(evt.target);
                            resolve(evt.target);
                        }
                    });
                });
                var taskHandler = item[_this.type];
                taskHandler.call(item, _this.options);
            });
            asyncTasks.push(task);
        };
        var this_1 = this;
        while (this._stack.length) {
            _loop_1();
        }
        if (!asyncTasks.length)
            return;
        Promise.all(asyncTasks)
            .then(function (items) {
            if (_this.debug) {
                console.log("%c[IBSheetLoader] ".concat(_this.type, " tasks all done -- ").concat((0, lodash_1.now)() - startTime, "ms"), 'color: green');
            }
            _this.emit(interface_1.LoaderEventName.LOAD_COMPLETE, { target: _this, data: items });
            _this._working = false;
            _this._resolveJobs();
        })
            .catch(function (err) {
            _this.emit(interface_1.LoaderEventName.LOAD_FAILED, { target: _this, error: err });
            _this._working = false;
            throw new Error(err);
        });
    };
    LoaderTaskManager.prototype.start = function () {
        var _this = this;
        (0, dom_utils_1.documentReady)(function () { return _this._start(); });
    };
    return LoaderTaskManager;
}(custom_1.CustomEventEmitter));
exports.LoaderTaskManager = LoaderTaskManager;
//# sourceMappingURL=task-manager.js.map