"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const Peer_1 = require("../../../../../api/peer/Peer");
const Semifunctional_1 = require("../../../../../Class/Semifunctional");
const makeUnitRemoteRef_1 = require("../../../../../client/makeUnitRemoteRef");
const STRING_1 = require("../../../../../constant/STRING");
const evaluate_1 = require("../../../../../spec/evaluate");
const stringify_1 = require("../../../../../spec/stringify");
const _ids_1 = require("../../../../_ids");
class PeerShareGraph extends Semifunctional_1.Semifunctional {
    constructor(system) {
        super({
            fi: ['graph', 'opt'],
            fo: ['offer'],
            i: ['answer', 'close'],
            o: [],
        }, {
            input: {
                graph: {
                    ref: true,
                },
            },
        }, system, _ids_1.ID_PEER_SHARE_GRAPH);
        this.__ = ['U'];
        this._connected = false;
        this._disconnect = () => {
            this._send_terminate();
            this._peer = null;
        };
        this._close = () => {
            this._ref = null;
        };
        this._send = (data) => {
            const message = (0, stringify_1.stringify)(data);
            this._peer.send(message);
        };
        this._send_init = () => {
            this._send({ type: STRING_1.INIT });
        };
        this._send_exec = (data) => {
            this._send({ type: STRING_1.EXEC, data });
        };
        this._send_terminate = () => {
            if (this._connected) {
                this._send({ type: STRING_1.TERMINATE });
            }
        };
        this.addListener('destroy', () => {
            // console.log('PeerShareGraph', 'destroy')
            if (this._connected) {
                this._disconnect();
                this._close();
            }
        });
    }
    f({ graph, opt }, done) {
        const peer = new Peer_1.Peer(this.__system, true, opt);
        this._connected = false;
        peer.addListener('connect', () => {
            // console.log('PeerShareGraph', 'connect')
            this._connected = true;
            if (this._input.graph.active()) {
                this._send_init();
            }
        });
        peer.addListener('close', () => {
            // console.log('PeerShareGraph', 'close')
            this._connected = false;
        });
        peer.addListener('message', (message) => {
            // console.log('PeerShareGraph', 'message', message)
            if (this._ref) {
                const specs = this.__system.specs;
                const classes = this.__system.classes;
                const data = (0, evaluate_1.evaluate)(message, specs, classes);
                this._ref.exec(data);
            }
        });
        this._peer = peer;
        (() => __awaiter(this, void 0, void 0, function* () {
            const offer = yield peer.offer();
            done({
                offer,
            });
        }))();
        const ref = (0, makeUnitRemoteRef_1.makeUnitRemoteRef)(graph, ['U', 'C', 'G', 'EE'], (data) => {
            this._send_exec(data);
        });
        this._ref = ref;
        if (this._connected) {
            this._send_init();
        }
        if (this._input.answer.active()) {
            ;
            (() => __awaiter(this, void 0, void 0, function* () {
                yield this._peer.acceptAnswer(this._input.answer.peak());
            }))();
        }
    }
    d() {
        this._disconnect();
    }
    onIterDataInputData(name, data) {
        return __awaiter(this, void 0, void 0, function* () {
            if (name === 'answer') {
                if (this._peer) {
                    yield this._peer.acceptAnswer(data);
                }
            }
            else if (name === 'close') {
                this._disconnect();
            }
        });
    }
    onIterDataInputDrop(name) {
        return __awaiter(this, void 0, void 0, function* () {
            if (name === 'answer') {
                this._disconnect();
            }
        });
    }
}
exports.default = PeerShareGraph;
//# sourceMappingURL=index.js.map