"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const es6_promisify_1 = require("es6-promisify");
const loggingService_1 = require("./loggingService");
const utils_1 = require("./utils");
const absoluteVote_1 = require("./wrappers/absoluteVote");
const auction4Reputation_1 = require("./wrappers/auction4Reputation");
const contributionReward_1 = require("./wrappers/contributionReward");
const daoCreator_1 = require("./wrappers/daoCreator");
const daoToken_1 = require("./wrappers/daoToken");
const erc20_1 = require("./wrappers/erc20");
const externalLocking4Reputation_1 = require("./wrappers/externalLocking4Reputation");
const fixedReputationAllocation_1 = require("./wrappers/fixedReputationAllocation");
const genericScheme_1 = require("./wrappers/genericScheme");
const genesisProtocol_1 = require("./wrappers/genesisProtocol");
const globalConstraintRegistrar_1 = require("./wrappers/globalConstraintRegistrar");
const intVoteInterface_1 = require("./wrappers/intVoteInterface");
const lockingEth4Reputation_1 = require("./wrappers/lockingEth4Reputation");
const lockingToken4Reputation_1 = require("./wrappers/lockingToken4Reputation");
const redeemer_1 = require("./wrappers/redeemer");
const reputation_1 = require("./wrappers/reputation");
const schemeRegistrar_1 = require("./wrappers/schemeRegistrar");
const tokenCapGC_1 = require("./wrappers/tokenCapGC");
const upgradeScheme_1 = require("./wrappers/upgradeScheme");
const vestingScheme_1 = require("./wrappers/vestingScheme");
const voteInOrganizationScheme_1 = require("./wrappers/voteInOrganizationScheme");
/**
 * Service that provides access to Arc.js contract wrapper classes and class factories.
 */
class WrapperService {
    /**
     * initialize() must be called before any of the static properties will have values.
     * It is called by ArcInitialize(), which in tur must be invoked by any application using Arc.js.
     *
     * @param options
     */
    static initialize(options = {}) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            loggingService_1.LoggingService.debug('WrapperService: initializing');
            /**
             * Deployed contract wrappers by name.
             */
            const filter = (options.filter) ?
                Object.assign({}, WrapperService.noWrappersFilter, options.filter) :
                WrapperService.allWrappersFilter;
            WrapperService.wrappers.AbsoluteVote = filter.AbsoluteVote ? yield absoluteVote_1.AbsoluteVoteFactory.deployed() : null;
            WrapperService.wrappers.ContributionReward = filter.ContributionReward ? yield contributionReward_1.ContributionRewardFactory.deployed() : null;
            WrapperService.wrappers.DaoCreator = filter.DaoCreator ? yield daoCreator_1.DaoCreatorFactory.deployed() : null;
            WrapperService.wrappers.GenesisProtocol = filter.GenesisProtocol ? yield genesisProtocol_1.GenesisProtocolFactory.deployed() : null;
            WrapperService.wrappers.GenericScheme = filter.GenericScheme ? yield genericScheme_1.GenericSchemeFactory.deployed() : null;
            WrapperService.wrappers.GlobalConstraintRegistrar = filter.GlobalConstraintRegistrar ? yield globalConstraintRegistrar_1.GlobalConstraintRegistrarFactory.deployed() : null;
            WrapperService.wrappers.Redeemer = filter.Redeemer ? yield redeemer_1.RedeemerFactory.deployed() : null;
            WrapperService.wrappers.SchemeRegistrar = filter.SchemeRegistrar ? yield schemeRegistrar_1.SchemeRegistrarFactory.deployed() : null;
            WrapperService.wrappers.TokenCapGC = filter.TokenCapGC ? yield tokenCapGC_1.TokenCapGCFactory.deployed() : null;
            WrapperService.wrappers.UpgradeScheme = filter.UpgradeScheme ? yield upgradeScheme_1.UpgradeSchemeFactory.deployed() : null;
            WrapperService.wrappers.VestingScheme = filter.VestingScheme ? yield vestingScheme_1.VestingSchemeFactory.deployed() : null;
            WrapperService.wrappers.VoteInOrganizationScheme = filter.VoteInOrganizationScheme ? yield voteInOrganizationScheme_1.VoteInOrganizationSchemeFactory.deployed() : null;
            /**
             * Contract wrappers grouped by type
             */
            WrapperService.wrappersByType.allWrappers = Object.values(WrapperService.wrappers);
            WrapperService.wrappersByType.globalConstraints = [
                WrapperService.wrappers.TokenCapGC,
            ];
            WrapperService.wrappersByType.other = [
                WrapperService.wrappers.DaoCreator,
                WrapperService.wrappers.Redeemer,
            ];
            WrapperService.wrappersByType.nonUniversalSchemes = [];
            WrapperService.wrappersByType.universalSchemes = [
                WrapperService.wrappers.ContributionReward,
                WrapperService.wrappers.GlobalConstraintRegistrar,
                WrapperService.wrappers.SchemeRegistrar,
                WrapperService.wrappers.GenericScheme,
                WrapperService.wrappers.UpgradeScheme,
                WrapperService.wrappers.VestingScheme,
                WrapperService.wrappers.VoteInOrganizationScheme,
            ];
            WrapperService.wrappersByType.votingMachines = [
                WrapperService.wrappers.AbsoluteVote,
                WrapperService.wrappers.GenesisProtocol,
            ];
            /**
             * factories by name.  This particular way of initializing the object is due to a
             * weird thing in typedocs where it doesn't treat `factories` as a property of `WrapperService`
             * unless we initialize it this way (otherwise it shows up in the "Object Literal" section).
             */
            WrapperService.factories.AbsoluteVote = absoluteVote_1.AbsoluteVoteFactory;
            WrapperService.factories.ContributionReward = contributionReward_1.ContributionRewardFactory;
            WrapperService.factories.DaoCreator = daoCreator_1.DaoCreatorFactory;
            WrapperService.factories.DaoToken = daoToken_1.DaoTokenFactory;
            WrapperService.factories.GenesisProtocol = genesisProtocol_1.GenesisProtocolFactory;
            WrapperService.factories.GenericScheme = genericScheme_1.GenericSchemeFactory;
            WrapperService.factories.GlobalConstraintRegistrar = globalConstraintRegistrar_1.GlobalConstraintRegistrarFactory;
            WrapperService.factories.IntVoteInterface = intVoteInterface_1.IntVoteInterfaceFactory;
            WrapperService.factories.LockingEth4Reputation = lockingEth4Reputation_1.LockingEth4ReputationFactory;
            WrapperService.factories.LockingToken4Reputation = lockingToken4Reputation_1.LockingToken4ReputationFactory;
            WrapperService.factories.Auction4Reputation = auction4Reputation_1.Auction4ReputationFactory;
            WrapperService.factories.FixedReputationAllocation = fixedReputationAllocation_1.FixedReputationAllocationFactory;
            WrapperService.factories.ExternalLocking4Reputation = externalLocking4Reputation_1.ExternalLocking4ReputationFactory;
            WrapperService.factories.Redeemer = redeemer_1.RedeemerFactory;
            WrapperService.factories.Reputation = reputation_1.ReputationFactory;
            WrapperService.factories.SchemeRegistrar = schemeRegistrar_1.SchemeRegistrarFactory;
            WrapperService.factories.Erc20 = erc20_1.Erc20Factory;
            WrapperService.factories.TokenCapGC = tokenCapGC_1.TokenCapGCFactory;
            WrapperService.factories.UpgradeScheme = upgradeScheme_1.UpgradeSchemeFactory;
            WrapperService.factories.VestingScheme = vestingScheme_1.VestingSchemeFactory;
            WrapperService.factories.VoteInOrganizationScheme = voteInOrganizationScheme_1.VoteInOrganizationSchemeFactory;
            WrapperService.nonUniversalSchemeFactories.LockingEth4Reputation = WrapperService.factories.LockingEth4Reputation;
            WrapperService.nonUniversalSchemeFactories.LockingToken4Reputation = WrapperService.factories.LockingToken4Reputation;
            WrapperService.nonUniversalSchemeFactories.Auction4Reputation = WrapperService.factories.Auction4Reputation;
            WrapperService.nonUniversalSchemeFactories.FixedReputationAllocation = WrapperService.factories.FixedReputationAllocation;
            WrapperService.nonUniversalSchemeFactories.ExternalLocking4Reputation = WrapperService.factories.ExternalLocking4Reputation;
            WrapperService.universalSchemeFactories.ContributionReward = WrapperService.factories.ContributionReward;
            WrapperService.universalSchemeFactories.GlobalConstraintRegistrar = WrapperService.factories.GlobalConstraintRegistrar;
            WrapperService.universalSchemeFactories.GenericScheme = WrapperService.factories.GenericScheme;
            WrapperService.universalSchemeFactories.SchemeRegistrar = WrapperService.factories.SchemeRegistrar;
            WrapperService.universalSchemeFactories.UpgradeScheme = WrapperService.factories.UpgradeScheme;
            WrapperService.universalSchemeFactories.VestingScheme = WrapperService.factories.VestingScheme;
            WrapperService.universalSchemeFactories.VoteInOrganizationScheme = WrapperService.factories.VoteInOrganizationScheme;
            WrapperService.schemeFactories = Object.assign({}, WrapperService.nonUniversalSchemeFactories, WrapperService.universalSchemeFactories);
            /**
             * TODO: this should be made aware of previously-deployed GCs
             */
            /* tslint:disable-next-line:forin */
            for (const wrapperName in WrapperService.wrappers) {
                const wrapper = WrapperService.wrappers[wrapperName];
                if (wrapper) {
                    WrapperService.wrappersByAddress.set(wrapper.address, wrapper);
                }
            }
        });
    }
    /**
     * Returns the promise of an Arc.js contract wrapper or undefined if not found.
     *
     * Most useful when you have both contract name and maybe the address and wish to most
     * efficiently return the associated wrapper, or undefined when not found.
     *
     * @param contractName - name of an Arc contract, like "SchemeRegistrar"
     * @param address - optional
     */
    static getContractWrapper(contractName, address) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const factories = yield WrapperService.factories;
            const factory = factories[contractName];
            if (!factory) {
                return undefined;
            }
            if (address) {
                return factory.at(address)
                    .then((resultingContract) => resultingContract, () => undefined);
            }
            else {
                return Promise.resolve(WrapperService.wrappers[contractName]);
            }
        });
    }
    /**
     * Confirm the given contract wrapper wraps the same contract as it purports to,
     * and is the one deployed in the running version of Arc.js.
     *
     * This will reject wrappers of different versions of contracts with the same name in Arc.
     * @param contractNameWant
     * @param contractWrapperFound
     */
    static confirmContractType(contractWrapperFound) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const contractNameWant = contractWrapperFound.name;
            const web3 = yield utils_1.Utils.getWeb3();
            const deployedWrapperWant = WrapperService.wrappers[contractNameWant];
            const byteCodeWant = yield es6_promisify_1.promisify((callback) => web3.eth.getCode(deployedWrapperWant.address, callback))();
            const byteCodeFound = yield es6_promisify_1.promisify((callback) => web3.eth.getCode(contractWrapperFound.address, callback))();
            return byteCodeWant === byteCodeFound;
        });
    }
}
/**
 * Wrappers by name, hydrated with contracts as deployed by the running version of Arc.js.
 */
WrapperService.wrappers = {};
/**
 * Contract wrapper factories grouped by type
 */
WrapperService.wrappersByType = {};
/**
 * Wrapper factories by name.  Use these when you want to do `.at()` or `.new()`.  You can also
 * use for `deployed()`, but the wrappers for deployed contracts are directly available from the
 * `wrappers` and `wrappersByType` properties.
 */
WrapperService.factories = {};
/**
 * Universal scheme contract wrapper factories by name.
 */
WrapperService.universalSchemeFactories = {};
/**
 * Non-universal scheme contract wrapper factories by name.
 */
WrapperService.nonUniversalSchemeFactories = {};
/**
 * All scheme contract wrapper factories by name.
 */
WrapperService.schemeFactories = {};
/**
 * Map of contract wrappers keyed by address.  For example:
 *
 * `const wrapper = WrapperService.wrappersByAddress.get(anAddress);`
 *
 * Currently only returns the wrappers for contracts that were deployed by the running
 * version of Arc.js.
 */
WrapperService.wrappersByAddress = new Map();
WrapperService.allWrappersFilter = {
    AbsoluteVote: true,
    ContributionReward: true,
    DaoCreator: true,
    GenericScheme: true,
    GenesisProtocol: true,
    GlobalConstraintRegistrar: true,
    Redeemer: true,
    SchemeRegistrar: true,
    TokenCapGC: true,
    UpgradeScheme: true,
    VestingScheme: true,
    VoteInOrganizationScheme: true,
};
WrapperService.noWrappersFilter = {
    AbsoluteVote: false,
    ContributionReward: false,
    DaoCreator: false,
    GenericScheme: false,
    GenesisProtocol: false,
    GlobalConstraintRegistrar: false,
    Redeemer: false,
    SchemeRegistrar: false,
    TokenCapGC: false,
    UpgradeScheme: false,
    VestingScheme: false,
    VoteInOrganizationScheme: false,
};
exports.WrapperService = WrapperService;
/**
 * for quicker access to the contract wrappers
 */
exports.ContractWrappers = WrapperService.wrappers;
/**
 * for quicker access to the contract wrapper factories
 */
exports.ContractWrapperFactories = WrapperService.factories;
/**
 * for quicker access to the contract wrapper types
 */
exports.ContractWrappersByType = WrapperService.wrappersByType;
/**
 * for quicker access to the contract wrappers by address
 */
exports.ContractWrappersByAddress = WrapperService.wrappersByAddress;
exports.UniversalSchemeFactories = WrapperService.universalSchemeFactories;
exports.NonUniversalSchemeFactories = WrapperService.nonUniversalSchemeFactories;
exports.SchemeFactories = WrapperService.schemeFactories;
//# sourceMappingURL=wrapperService.js.map