"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 });
exports.AsyncG = exports.AsyncGRef = exports.AsyncGWatch = exports.AsyncGCall = void 0;
const Graph_1 = require("../../../Class/Graph");
const spec_1 = require("../../../client/spec");
const watchGraph_1 = require("../../../debug/graph/watchGraph");
const watchUnit_1 = require("../../../debug/watchUnit");
const proxyWrap_1 = require("../../../proxyWrap");
const evaluate_1 = require("../../../spec/evaluate");
const fromId_1 = require("../../../spec/fromId");
const stringify_1 = require("../../../spec/stringify");
const stringifySpec_1 = require("../../../spec/stringifySpec");
const f_1 = require("../../../system/core/object/ForEachKeyValue/f");
const object_1 = require("../../../util/object");
const weakMerge_1 = require("../../../weakMerge");
const stringifyPinData_1 = require("../../stringifyPinData");
const Async_1 = require("./Async");
const AsyncGCall = (graph) => {
    return {
        $setUnitId({ unitId, newUnitId, name, specId }) {
            graph.setUnitId(unitId, newUnitId, name, specId);
        },
        $setUnitPinData({ unitId, pinId, type, data, }) {
            const system = graph.__system;
            const { specs, classes } = system;
            const _specs = system.specs;
            data = (0, evaluate_1.evaluate)(data, (0, weakMerge_1.weakMerge)(specs, _specs), classes);
            graph.setUnitPinData(unitId, type, pinId, data);
        },
        $removeUnitPinData({ unitId, type, pinId, }) {
            graph.removeUnitPinData(unitId, type, pinId);
        },
        $addUnit({ unitId: id, bundle }) {
            graph.addUnitSpec(id, bundle);
        },
        $cloneUnit({ unitId, newUnitId }) {
            graph.cloneUnit(unitId, newUnitId);
        },
        $moveUnit({ id, unitId, inputId }) {
            graph.moveUnit(id, unitId, inputId);
        },
        $addUnits({ units }) {
            const { specs, classes } = graph.__system;
            const unitNodes = (0, object_1.mapObjVK)(units, (u) => (Object.assign(Object.assign({}, u), { Class: (0, fromId_1.bundleFromId)(u.id, specs, classes) })));
            graph.addUnitSpecs(unitNodes);
        },
        $removeUnit({ unitId }) {
            graph.removeUnit(unitId);
        },
        $exposePinSet({ type, pinId, pinSpec: pin, data }) {
            const data_ = data && (0, evaluate_1.evaluate)(data, graph.__system.specs, graph.__system.classes);
            graph.exposePinSet(type, pinId, pin, data_);
        },
        $coverPinSet({ type, pinId }) {
            graph.coverPinSet(type, pinId, true);
        },
        $exposePin({ type, pinId, subPinId, subPinSpec }) {
            graph.exposePin(type, pinId, subPinId, subPinSpec);
        },
        $coverPin({ type, pinId, subPinId }) {
            graph.coverPin(type, pinId, subPinId);
        },
        $plugPin({ type, pinId, subPinId, subPinSpec }) {
            graph.plugPin(type, pinId, subPinId, subPinSpec);
        },
        $unplugPin({ type, pinId, subPinId }) {
            graph.unplugPin(type, pinId, subPinId);
        },
        $exposeUnitPinSet({ unitId, type, pinId, pinSpec, }) {
            const unit = graph.getUnit(unitId);
            unit.exposePinSet(type, pinId, pinSpec);
        },
        $coverUnitPinSet({ unitId, type, pinId }) {
            const unit = graph.getUnit(unitId);
            unit.coverPinSet(type, pinId);
        },
        $setPinSetId({ type, pinId, nextPinId }) {
            graph.setPinSetId(type, pinId, nextPinId);
        },
        $setPinSetFunctional({ type, pinId, functional, }) {
            graph.setPinSetFunctional(type, pinId, functional);
        },
        $setUnitPinConstant({ unitId, type, pinId, constant, }) {
            graph.setUnitPinConstant(unitId, type, pinId, constant);
        },
        $setUnitPinIgnored({ unitId, type, pinId, ignored, }) {
            graph.setUnitPinIgnored(unitId, type, pinId, ignored);
        },
        $setUnitPinSetId({ unitId, type, pinId, nextPinId, }) {
            graph.setUnitPinSetId(unitId, type, pinId, nextPinId);
        },
        $addMerge({ mergeId, mergeSpec: merge }) {
            graph.addMerge(merge, mergeId);
        },
        $removeMerge({ mergeId }) {
            graph.removeMerge(mergeId, true, false);
        },
        $addMerges({ merges }) {
            graph.addMerges(merges);
        },
        $setMergeData({ mergeId, data }) {
            const system = graph.refSystem();
            const { specs, classes } = system;
            const _data = (0, evaluate_1.evaluate)(data, specs, classes);
            graph.setMergeData(mergeId, _data);
        },
        $removeMergeData({ mergeId }) {
            graph.removeMergeData(mergeId);
        },
        $addPinToMerge({ mergeId, unitId, type, pinId, }) {
            graph.addPinToMerge(mergeId, unitId, type, pinId);
        },
        $removePinFromMerge({ mergeId, unitId, type, pinId, }) {
            graph.removePinFromMerge(mergeId, unitId, type, pinId);
        },
        $takeUnitErr({ unitId }) {
            graph.takeUnitErr(unitId);
        },
        $removeUnitGhost({ unitId, nextUnitId, nextUnitSpec, }, callback) {
            const ghost = graph.removeUnitGhost(unitId, nextUnitId, nextUnitSpec);
            (0, stringifySpec_1.stringifyUnitBundleSpecData)(ghost.bundle);
            callback(ghost);
        },
        $addUnitGhost({ unitId, nextUnitId, nextUnitBundle, nextUnitPinMap, }) {
            graph.addUnitGhost(unitId, nextUnitId, nextUnitBundle, nextUnitPinMap);
        },
        $getBundle({}, callback) {
            const bundle = graph.getBundleSpec();
            const { spec } = bundle;
            (0, stringifySpec_1.stringifyGraphSpecData)(spec);
            callback(bundle);
        },
        $getUnitPinData({ unitId, type, pinId }, callback) {
            const state = graph.getUnitData(unitId, type, pinId);
            callback(state);
        },
        $getUnitState({ unitId }, callback) {
            return __awaiter(this, void 0, void 0, function* () {
                const state = yield graph.getUnitState(unitId);
                callback(state);
            });
        },
        $getGraphData(data, callback) {
            const state = graph.getGraphState();
            const children = graph.getGraphChildren();
            const err = graph.getGraphErr();
            const units = graph.getUnits();
            const pinData = {};
            (0, f_1.default)(units, (unit, unitId) => {
                const unitPinData = unit.getPinsData();
                const _unitPinData = (0, stringifyPinData_1.stringifyPinData)(unitPinData);
                pinData[unitId] = _unitPinData;
            });
            const _mergeData = graph.getGraphMergeInputData();
            const mergeData = {};
            for (const mergeId in _mergeData) {
                const data = _mergeData[mergeId];
                Performance;
                if (data === undefined) {
                    mergeData[mergeId] = undefined;
                }
                else {
                    mergeData[mergeId] = (0, stringify_1.stringify)(data);
                }
            }
            callback({ state, children, err, pinData, mergeData });
        },
        $snapshot(data, callback) {
            return __awaiter(this, void 0, void 0, function* () {
                const memory = graph.snapshot();
                callback(memory);
            });
        },
        $snapshotUnit({ unitId }, callback) {
            const unit = graph.getUnit(unitId);
            const memory = unit.snapshot();
            (0, stringifySpec_1.stringifyMemorySpecData)(memory);
            callback(memory);
        },
        $getGraphState({}, callback) {
            return __awaiter(this, void 0, void 0, function* () {
                const state = yield graph.getGraphState();
                callback(state);
            });
        },
        $getGraphChildren({}, callback) {
            const children = graph.getGraphChildren();
            callback(children);
        },
        $getGraphErr({}, callback) {
            const state = graph.getGraphErr();
            callback(state);
        },
        $getGraphPinData({}, callback) {
            const pinData = {};
            const units = graph.getUnits();
            (0, f_1.default)(units, (unit, unitId) => {
                const unitPinData = unit.getPinsData();
                const _unitPinData = (0, stringifyPinData_1.stringifyPinData)(unitPinData);
                pinData[unitId] = _unitPinData;
            });
            callback(pinData);
        },
        $getGraphMergeInputData({}, callback) {
            const mergeData = graph.getGraphMergeInputData();
            const _mergeData = (0, stringifyPinData_1.stringifyDataObj)(mergeData);
            callback(_mergeData);
        },
        $getUnitInputData({ unitId }, callback) {
            const state = graph.getUnitInputData(unitId);
            callback(state);
        },
        $setMetadata({ path, data }) {
            graph.setMetadata(path, data);
        },
        $reorderSubComponent({ parentId, childId, to, }) {
            graph.reorderSubComponent(parentId, childId, to);
        },
        $moveSubComponentRoot({ parentId, children, slotMap, }) {
            graph.moveSubComponentRoot(parentId, children, slotMap);
        },
        $moveSubgraphInto({ graphId, nextSpecId, nodeIds, nextIdMap, nextPinIdMap, nextMergePinId, nextPlugSpec, nextSubComponentParentMap, nextSubComponentChildrenMap, }) {
            const graphBundle = graph.getGraphUnitBundleSpec(graphId);
            graph.moveSubgraphInto(graphId, graphBundle, nextSpecId, nodeIds, nextIdMap, nextPinIdMap, nextMergePinId, nextPlugSpec, nextSubComponentParentMap, nextSubComponentChildrenMap);
        },
        $moveSubgraphOutOf({ graphId, nextSpecId, nodeIds, nextIdMap, nextPinIdMap, nextMergePinId, nextPlugSpec, nextSubComponentParentMap, nextSubComponentChildrenMap, }) {
            const graphBundle = graph.getGraphUnitBundleSpec(graphId);
            graph.moveSubgraphInto(graphId, graphBundle, nextSpecId, nodeIds, nextIdMap, nextPinIdMap, nextMergePinId, nextPlugSpec, nextSubComponentParentMap, nextSubComponentChildrenMap);
        },
        $bulkEdit({ actions }) {
            graph.bulkEdit(actions);
        },
    };
};
exports.AsyncGCall = AsyncGCall;
const AsyncGWatch = (graph) => {
    return {
        $watchGraph({ events }, callback) {
            return (0, watchGraph_1.watchGraph)(graph, callback, events);
        },
        $watchUnit({ unitId, events }, callback) {
            const unit = graph.getUnit(unitId);
            return (0, watchUnit_1.watchUnit)(unit, callback, events);
        },
        $watchGraphUnit({ unitId, events }, callback) {
            const graph = this.refUnit(unitId);
            return (0, watchGraph_1.watchGraph)(graph, callback, events);
        },
        $watchUnitPath({ path, events }, callback) {
            const unit = graph.getUnitByPath(path);
            return (0, watchUnit_1.watchUnit)(unit, callback, events);
        },
        $watchGraphUnitPath({ path, events }, callback) {
            const unit = graph.getUnitByPath(path);
            return (0, watchGraph_1.watchGraph)(unit, callback, events);
        },
    };
};
exports.AsyncGWatch = AsyncGWatch;
const AsyncGRef = (graph) => {
    return {
        $compose({ id, unitId, _, }) {
            const system = graph.refSystem();
            const spec = graph.getSpec();
            if (system.hasSpec(id)) {
                throw new Error(`spec with id '${id}' already exists`);
            }
            const render = spec.component && !(0, object_1.isEmptyObject)(spec.component.subComponents || {});
            if (render) {
                graph.setElement();
            }
            else {
                graph.setNotElement();
            }
            const parentSpec = (0, spec_1.emptySpec)({ id });
            system.setSpec(id, parentSpec);
            const parent = new Graph_1.Graph(parentSpec, {}, system);
            parent.addUnit(unitId, graph, undefined, false);
            parent.play();
            const $parent = (0, Async_1.Async)(parent, _);
            return (0, proxyWrap_1.proxyWrap)($parent, _);
        },
        $refUnit({ unitId, _ }) {
            const unit = graph.getUnit(unitId);
            const $unit = (0, Async_1.Async)(unit, _);
            return (0, proxyWrap_1.proxyWrap)($unit, _);
        },
        $refSubComponent({ unitId, _, }) {
            const unit = graph.getUnit(unitId);
            const $unit = (0, Async_1.Async)(unit, _);
            return (0, proxyWrap_1.proxyWrap)($unit, _);
        },
    };
};
exports.AsyncGRef = AsyncGRef;
const AsyncG = (graph) => {
    return Object.assign(Object.assign(Object.assign({}, (0, exports.AsyncGWatch)(graph)), (0, exports.AsyncGCall)(graph)), (0, exports.AsyncGRef)(graph));
};
exports.AsyncG = AsyncG;
//# sourceMappingURL=AsyncG.js.map