"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("./wrap/lodash");
const log_1 = require("./log");
const function_1 = require("./function");
const imitate_1 = require("./imitate");
const proxy_1 = require("./object/proxy");
const DEFAULT_OPTIONS = { excludeMethods: ['then'] };
function object(nameOrType, config) {
    return lodash_1.default.tap(fakeObject(nameOrType, config, arguments.length), (obj) => {
        addToStringToDouble(obj, nameOrType);
    });
}
exports.default = object;
const fakeObject = function (nameOrType, config, argCount) {
    if (lodash_1.default.isArray(nameOrType)) {
        return createTestDoublesForFunctionNames(nameOrType);
    }
    else if (lodash_1.default.isObjectLike(nameOrType)) {
        return (0, imitate_1.default)(nameOrType);
    }
    else if (lodash_1.default.isString(nameOrType) || argCount === 0) {
        return (0, proxy_1.default)(nameOrType, withDefaults(config));
    }
    else if (lodash_1.default.isFunction(nameOrType)) {
        ensureFunctionIsNotPassed();
    }
    else {
        ensureOtherGarbageIsNotPassed();
    }
};
const createTestDoublesForFunctionNames = (names) => lodash_1.default.transform(names, (acc, funcName) => {
    acc[funcName] = (0, function_1.default)(`.${String(funcName)}`);
}, {});
const ensureFunctionIsNotPassed = () => log_1.default.error('td.object', 'Functions are not valid arguments to `td.object` (as of testdouble@2.0.0). Please use `td.function()`, `td.constructor()` or `td.instance()` instead for creating fake functions.');
const ensureOtherGarbageIsNotPassed = () => log_1.default.error('td.object', `\
To create a fake object with td.object(), pass it a plain object that contains
functions, an array of function names, or (if your runtime supports ES Proxy
objects) a string name.

If you passed td.object an instance of a custom type, consider passing the
type's constructor to \`td.constructor()\` instead.
`);
const withDefaults = (config) => lodash_1.default.extend({}, DEFAULT_OPTIONS, config);
const addToStringToDouble = (fakeObject, nameOrType) => {
    const name = nameOf(nameOrType);
    fakeObject.toString = () => `[test double object${name ? ` for "${name}"` : ''}]`;
};
const nameOf = (nameOrType) => lodash_1.default.isString(nameOrType)
    ? nameOrType
    : '';
