"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeRemoteUnitAPI = exports.remoteRef = void 0;
const _C_1 = require("../types/interface/async/$C");
const _CA_1 = require("../types/interface/async/$CA");
const _EE_1 = require("../types/interface/async/$EE");
const _G_1 = require("../types/interface/async/$G");
const _J_1 = require("../types/interface/async/$J");
const _MS_1 = require("../types/interface/async/$MS");
const _S_1 = require("../types/interface/async/$S");
const _U_1 = require("../types/interface/async/$U");
const _V_1 = require("../types/interface/async/$V");
const AsyncC_1 = require("../types/interface/async/AsyncC");
const AsyncCA_1 = require("../types/interface/async/AsyncCA");
const AsyncEE_1 = require("../types/interface/async/AsyncEE");
const AsyncG_1 = require("../types/interface/async/AsyncG");
const AsyncJ_1 = require("../types/interface/async/AsyncJ");
const AsyncMS_1 = require("../types/interface/async/AsyncMS");
const AsyncS_1 = require("../types/interface/async/AsyncS");
const AsyncU_1 = require("../types/interface/async/AsyncU");
const AsyncV_1 = require("../types/interface/async/AsyncV");
const METHOD = {
    EE: {
        call: _EE_1.EE_METHOD_CALL,
        watch: _EE_1.EE_METHOD_WATCH,
        ref: _EE_1.EE_METHOD_REF,
    },
    U: {
        call: _U_1.U_METHOD_CALL,
        watch: _U_1.U_METHOD_WATCH,
        ref: _U_1.U_METHOD_REF,
    },
    G: {
        call: _G_1.G_METHOD_CALL,
        watch: _G_1.G_METHOD_WATCH,
        ref: _G_1.G_METHOD_REF,
    },
    C: {
        call: _C_1.C_METHOD_CALL,
        watch: _C_1.C_METHOD_WATCH,
        ref: _C_1.C_METHOD_REF,
    },
    V: {
        call: _V_1.V_METHOD_CALL,
        watch: _V_1.V_METHOD_WATCH,
        ref: _V_1.V_METHOD_REF,
    },
    J: {
        call: _J_1.J_METHOD_CALL,
        watch: _J_1.J_METHOD_WATCH,
        ref: _J_1.J_METHOD_REF,
    },
    MS: {
        call: _MS_1.MS_METHOD_CALL,
        watch: _MS_1.MS_METHOD_WATCH,
        ref: _MS_1.MS_METHOD_REF,
    },
    S: {
        call: _S_1.S_METHOD_CALL,
        watch: _S_1.S_METHOD_WATCH,
        ref: _S_1.S_METHOD_REF,
    },
    CA: {
        call: _CA_1.CA_METHOD_CALL,
        watch: _CA_1.CA_METHOD_WATCH,
        ref: _CA_1.CA_METHOD_REF,
    },
};
function remoteRef(ref) {
    let _ref = {};
    for (const name in ref) {
        const method = ref[name];
        const _method = (data) => {
            const { _ } = data;
            const $unit = method(data);
            const remoteApi = {
                call: {},
                watch: {},
                ref: {},
            };
            for (const __ of _) {
                const methods = METHOD[__];
                for (const type of ['call', 'watch', 'ref']) {
                    const methodList = methods[type];
                    for (const methodName of methodList) {
                        const $methodName = `$${methodName}`;
                        remoteApi[type][$methodName] = (...args) => {
                            const result = $unit[$methodName](...args);
                            return type === 'ref'
                                ? makeRemoteUnitAPI(result, result.__)
                                : result;
                        };
                    }
                }
            }
            return remoteApi;
        };
        _ref[name] = _method;
    }
    return _ref;
}
exports.remoteRef = remoteRef;
function makeRemoteUnitAPI(unit, _) {
    let call = {};
    let watch = {};
    let ref = {};
    for (const __ of _) {
        switch (__) {
            case 'EE':
                call = Object.assign(Object.assign({}, call), (0, AsyncEE_1.AsyncEECall)(unit));
                watch = Object.assign(Object.assign({}, watch), (0, AsyncEE_1.AsyncEEWatch)(unit));
                ref = Object.assign(Object.assign({}, ref), remoteRef((0, AsyncEE_1.AsyncEERef)(unit)));
                break;
            case 'U':
                call = Object.assign(Object.assign({}, call), (0, AsyncU_1.AsyncUCall)(unit));
                watch = Object.assign(Object.assign({}, watch), (0, AsyncU_1.AsyncUWatch)(unit));
                ref = Object.assign(Object.assign({}, ref), remoteRef((0, AsyncU_1.AsyncURef)(unit)));
                break;
            case 'C':
                call = Object.assign(Object.assign({}, call), (0, AsyncC_1.AsyncCCall)(unit));
                watch = Object.assign(Object.assign({}, watch), (0, AsyncC_1.AsyncCWatch)(unit));
                ref = Object.assign(Object.assign({}, ref), remoteRef((0, AsyncC_1.AsyncCRef)(unit)));
                break;
            case 'G':
                call = Object.assign(Object.assign({}, call), (0, AsyncG_1.AsyncGCall)(unit));
                watch = Object.assign(Object.assign({}, watch), (0, AsyncG_1.AsyncGWatch)(unit));
                ref = Object.assign(Object.assign({}, ref), remoteRef((0, AsyncG_1.AsyncGRef)(unit)));
                break;
            case 'V':
                call = Object.assign(Object.assign({}, call), (0, AsyncV_1.AsyncVCall)(unit));
                watch = Object.assign(Object.assign({}, watch), (0, AsyncV_1.AsyncVWatch)(unit));
                ref = Object.assign(Object.assign({}, ref), remoteRef((0, AsyncV_1.AsyncVRef)(unit)));
                break;
            case 'J':
                call = Object.assign(Object.assign({}, call), (0, AsyncJ_1.AsyncJCall)(unit));
                watch = Object.assign(Object.assign({}, watch), (0, AsyncJ_1.AsyncJWatch)(unit));
                ref = Object.assign(Object.assign({}, ref), remoteRef((0, AsyncJ_1.AsyncJRef)(unit)));
                break;
            case 'MS':
                call = Object.assign(Object.assign({}, call), (0, AsyncMS_1.AsyncMSCall)(unit));
                watch = Object.assign(Object.assign({}, watch), (0, AsyncMS_1.AsyncMSWatch)(unit));
                ref = Object.assign(Object.assign({}, ref), remoteRef((0, AsyncMS_1.AsyncMSRef)(unit)));
                break;
            case 'S':
                call = Object.assign(Object.assign({}, call), (0, AsyncS_1.AsyncSCall)(unit));
                watch = Object.assign(Object.assign({}, watch), (0, AsyncS_1.AsyncSWatch)(unit));
                ref = Object.assign(Object.assign({}, ref), remoteRef((0, AsyncS_1.AsyncSRef)(unit)));
                break;
            case 'CA':
                call = Object.assign(Object.assign({}, call), (0, AsyncCA_1.AsyncCACall)(unit));
                watch = Object.assign(Object.assign({}, watch), (0, AsyncCA_1.AsyncCAWatch)(unit));
                ref = Object.assign(Object.assign({}, ref), remoteRef((0, AsyncCA_1.AsyncCARef)(unit)));
                break;
            default:
                throw new Error('unknown interface');
        }
    }
    const API = {
        call,
        watch,
        ref,
    };
    return API;
}
exports.makeRemoteUnitAPI = makeRemoteUnitAPI;
//# sourceMappingURL=makeRemoteUnitAPI.js.map