"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Semifunctional_1 = require("../../../../Class/Semifunctional");
const Heap_1 = require("../../../../Heap");
const Waiter_1 = require("../../../../Waiter");
const _ids_1 = require("../../../_ids");
class Sort extends Semifunctional_1.Semifunctional {
    constructor(system) {
        super({
            fi: ['a'],
            fo: ['b'],
            i: ['a[i] < a[j]'],
            o: ['a[i]', 'a[j]'],
        }, {}, system, _ids_1.ID_SORT);
        this._forward_waiter = new Waiter_1.Waiter();
        this._backward_waiter = new Waiter_1.Waiter();
        this._predicate = async (a, b) => {
            this._forwarding = true;
            this._output['a[i]'].push(a);
            this._output['a[j]'].push(b);
            this._forwarding = false;
            const result = await this._forward_waiter.once();
            this._loop();
            this._forward_waiter.clear();
            this._input['a[i] < a[j]'].pull();
            await this._backward_waiter.once();
            this._backward_waiter.clear();
            return result;
        };
    }
    async f({ a }, done) {
        let heap = null;
        for (const value of a) {
            heap = await (0, Heap_1.asyncAddHeapNode)(heap, { parent: null, left: null, right: null, value }, this._predicate);
        }
        const b = heap ? await (0, Heap_1.asyncToSortedArray)(heap, this._predicate) : [];
        done({
            b,
        });
    }
    d() {
        this._forward_empty('a[i]');
        this._forward_empty('a[j]');
    }
    onIterDataInputData(name, data) {
        switch (name) {
            case 'a[i] < a[j]': {
                this._forward_waiter.set(data);
                break;
            }
        }
    }
    onIterDataOutputDrop(name) {
        // console.log('onIterDataOutputDrop', name)
        if (!this._forwarding) {
            this._loop();
        }
    }
    _loop() {
        if (this._output['a[i]'].empty() && this._output['a[j]'].empty()) {
            this._backward_waiter.set(true);
        }
    }
}
exports.default = Sort;
//# sourceMappingURL=index.js.map