import { __generator, __values } from "tslib";
export var createLinkedList = function () {
    var _a;
    var head;
    var tail;
    var unlinkItem = function (item) {
        if (item.previous !== undefined) {
            item.previous.next = item.next;
        }
        if (item.next !== undefined) {
            item.next.previous = item.previous;
        }
        if (head === item) {
            head = item.next;
            if (head !== undefined) {
                head.previous = undefined;
            }
        }
        if (tail === item) {
            tail = item.previous;
            if (tail !== undefined) {
                tail.next = undefined;
            }
        }
    };
    var push = function (item) {
        var entry = {
            next: undefined,
            previous: tail,
            item: item,
        };
        if (head === undefined) {
            head = entry;
            tail = entry;
            return;
        }
        tail.next = entry;
        tail = entry;
    };
    var shift = function () {
        if (head === undefined) {
            return undefined;
        }
        var drained = head;
        unlinkItem(drained);
        return drained.item;
    };
    var iterate = function () {
        var current;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    current = head;
                    _a.label = 1;
                case 1:
                    if (!(current !== undefined)) return [3 /*break*/, 3];
                    return [4 /*yield*/, current];
                case 2:
                    _a.sent();
                    current = current.next;
                    return [3 /*break*/, 1];
                case 3: return [2 /*return*/];
            }
        });
    };
    var iterateContent = function () {
        var current;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    current = head;
                    _a.label = 1;
                case 1:
                    if (!(current !== undefined)) return [3 /*break*/, 3];
                    return [4 /*yield*/, current.item];
                case 2:
                    _a.sent();
                    current = current.next;
                    return [3 /*break*/, 1];
                case 3: return [2 /*return*/];
            }
        });
    };
    var forEach = function (cb) {
        var e_1, _a;
        try {
            for (var _b = __values(iterate()), _c = _b.next(); !_c.done; _c = _b.next()) {
                var item = _c.value;
                cb(item.item);
            }
        }
        catch (e_1_1) { e_1 = { error: e_1_1 }; }
        finally {
            try {
                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
            }
            finally { if (e_1) throw e_1.error; }
        }
    };
    var map = function (cb) {
        var e_2, _a;
        var result = [];
        try {
            for (var _b = __values(iterate()), _c = _b.next(); !_c.done; _c = _b.next()) {
                var item = _c.value;
                result.push(cb(item.item));
            }
        }
        catch (e_2_1) { e_2 = { error: e_2_1 }; }
        finally {
            try {
                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
            }
            finally { if (e_2) throw e_2.error; }
        }
        return result;
    };
    var consumeOne = function (cb) {
        var e_3, _a;
        try {
            for (var _b = __values(iterate()), _c = _b.next(); !_c.done; _c = _b.next()) {
                var item = _c.value;
                if (cb(item.item)) {
                    unlinkItem(item);
                    return item.item;
                }
            }
        }
        catch (e_3_1) { e_3 = { error: e_3_1 }; }
        finally {
            try {
                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
            }
            finally { if (e_3) throw e_3.error; }
        }
    };
    var consumeAll = function (cb) {
        var e_4, _a;
        var result = [];
        try {
            for (var _b = __values(iterate()), _c = _b.next(); !_c.done; _c = _b.next()) {
                var item = _c.value;
                if (cb(item.item)) {
                    result.push(item.item);
                    unlinkItem(item);
                }
            }
        }
        catch (e_4_1) { e_4 = { error: e_4_1 }; }
        finally {
            try {
                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
            }
            finally { if (e_4) throw e_4.error; }
        }
        return result;
    };
    var clear = function () {
        head = undefined;
        tail = undefined;
    };
    return _a = {},
        _a[Symbol.iterator] = iterateContent,
        _a.push = push,
        _a.shift = shift,
        _a.forEach = forEach,
        _a.map = map,
        _a.consumeOne = consumeOne,
        _a.consumeAll = consumeAll,
        _a.clear = clear,
        _a;
};
