"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const theredoc = require("theredoc");
const lodash_1 = require("../wrap/lodash");
const log_1 = require("../log");
const function_1 = require("../function");
const store_1 = require("../store");
function proxy(name, { excludeMethods } = {}) {
    ensureProxySupport(name);
    return new Proxy({}, generateHandler(name, excludeMethods));
}
exports.default = proxy;
const ensureProxySupport = (name) => {
    if (typeof Proxy === 'undefined') {
        log_1.default.error('td.object', theredoc `\
      The current runtime does not have Proxy support, which is what
      testdouble.js depends on when a string name is passed to \`td.object()\`.

      More details here:
        https://github.com/testdouble/testdouble.js/blob/master/docs/4-creating-test-doubles.md#objectobjectname

      Did you mean \`td.object(['${name}'])\`?
    `);
    }
};
const generateHandler = (internalName, excludeMethods) => ({
    get(target, propKey) {
        return generateGet(target, propKey, internalName, excludeMethods);
    }
});
const generateGet = (target, propKey, internalName, excludeMethods) => {
    if (propKey === Symbol('__is_proxy')) {
        return true;
    }
    if (!Object.prototype.hasOwnProperty.call(target, propKey) &&
        !lodash_1.default.includes(excludeMethods, propKey)) {
        const nameWithProp = `${internalName || ''}.${String(propKey)}`;
        const tdFunc = function_1.default(nameWithProp);
        const tdFuncProxy = new Proxy(tdFunc, generateHandler(nameWithProp, excludeMethods));
        store_1.default.registerAlias(tdFunc, tdFuncProxy);
        target[propKey] = tdFuncProxy;
    }
    return target[propKey];
};
