"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const es6_promisify_1 = require("es6-promisify");
const contractWrapperFactory_1 = require("../contractWrapperFactory");
const utils_1 = require("../utils");
const web3EventService_1 = require("../web3EventService");
const locking4Reputation_1 = require("./locking4Reputation");
class ExternalLocking4ReputationWrapper extends locking4Reputation_1.Locking4ReputationWrapper {
    constructor() {
        super(...arguments);
        this.name = "ExternalLocking4Reputation";
        this.friendlyName = "External Locking For Reputation";
        this.factory = exports.ExternalLocking4ReputationFactory;
    }
    initialize(options) {
        const _super = name => super[name];
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield _super("_initialize").call(this, options, false);
            if (!options.externalLockingContract) {
                throw new Error("externalLockingContract is not defined");
            }
            if (!options.getBalanceFuncSignature) {
                throw new Error("getBalanceFuncSignature is not defined");
            }
            this.logContractFunctionCall("ExternalLocking4Reputation.initialize", options);
            return this.wrapTransactionInvocation("ExternalLocking4Reputation.initialize", options, this.contract.initialize, [options.avatarAddress,
                options.reputationReward,
                options.lockingStartTime.getTime() / 1000,
                options.lockingEndTime.getTime() / 1000,
                options.redeemEnableTime.getTime() / 1000,
                options.externalLockingContract,
                options.getBalanceFuncSignature]);
        });
    }
    getLockBlocker(options) {
        const _super = name => super[name];
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            /**
             * stub out lockerAddress, amount and period -- they aren't relevant to external locking validation.
             */
            const msg = yield _super("getLockBlocker").call(this, Object.assign({}, { lockerAddress: "0x", amount: "1", period: 1 }));
            if (msg) {
                return msg;
            }
            const alreadyLocked = yield this.getAccountHasLocked(options.lockerAddress);
            if (alreadyLocked) {
                return "account has already registered";
            }
            const currentAccount = (yield utils_1.Utils.getDefaultAccount()).toLowerCase();
            let lockerAddress = options.lockerAddress;
            if (lockerAddress && (lockerAddress.toLowerCase() === currentAccount)) {
                lockerAddress = 0;
            }
            if (lockerAddress && !(yield this.isRegistered(lockerAddress))) {
                throw new Error(`account does not own any MGN tokens`);
            }
        });
    }
    /**
     * Claim the MGN tokens and lock them.  Provide `lockerAddress` to claim on their behalf,
     * otherwise claims on behalf of the caller.
     * @param options
     */
    lock(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const msg = yield this.getLockBlocker(options);
            if (msg) {
                throw new Error(msg);
            }
            const currentAccount = (yield utils_1.Utils.getDefaultAccount()).toLowerCase();
            let lockerAddress = options.lockerAddress;
            if (lockerAddress && (lockerAddress.toLowerCase() === currentAccount)) {
                lockerAddress = 0;
            }
            this.logContractFunctionCall("ExternalLocking4Reputation.claim", options);
            return this.wrapTransactionInvocation("ExternalLocking4Reputation.claim", options, this.contract.claim, [lockerAddress]);
        });
    }
    /**
     * The caller is giving permission to the contract to allow someone else to claim
     * on their behalf.
     */
    register() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.logContractFunctionCall("ExternalLocking4Reputation.register");
            return this.wrapTransactionInvocation("ExternalLocking4Reputation.register", {}, this.contract.register, [], { from: yield utils_1.Utils.getDefaultAccount() });
        });
    }
    /**
     * Returns promise of whether the given locker has tokens that can be activated in the given MGN token contract.
     * Assumes that MGN token API is:  `lockedTokenBalances(address)`.
     *
     * @param lockerAddress
     * @param mgnTokenAddress
     */
    hasTokenToActivate(lockerAddress) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const balance = yield this.accountTokenBalance(lockerAddress);
            return balance.gt(0);
        });
    }
    /**
     * Returns the user's token balance
     * @param lockerAddress
     */
    accountTokenBalance(lockerAddress) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const web3 = yield utils_1.Utils.getWeb3();
            const tokenAddress = yield this.getExternalLockingContract();
            // tslint:disable
            const mgnToken = yield web3.eth.contract([
                {
                    constant: true,
                    inputs: [
                        {
                            name: "",
                            type: "address"
                        },
                    ],
                    name: "lockedTokenBalances",
                    outputs: [
                        {
                            name: "",
                            type: "uint256"
                        },
                    ],
                    payable: false,
                    stateMutability: "view",
                    "type": "function",
                }
            ]).at(tokenAddress);
            // tslint:enable
            return es6_promisify_1.promisify((callback) => mgnToken.lockedTokenBalances(lockerAddress, callback))();
        });
    }
    /**
     * Returns promise of a boolean indicating whether the given address has registered
     * to have their tokens claimed for them (see `register`).
     * @param lockerAddress
     */
    isRegistered(lockerAddress) {
        this.logContractFunctionCall("ExternalLocking4Reputation.registrar", { lockerAddress });
        return this.contract.registrar(lockerAddress);
    }
    getExternalLockingContract() {
        this.logContractFunctionCall("ExternalLocking4Reputation.externalLockingContract");
        return this.contract.externalLockingContract();
    }
    getGetBalanceFuncSignature() {
        this.logContractFunctionCall("ExternalLocking4Reputation.getBalanceFuncSignature");
        return this.contract.getBalanceFuncSignature();
    }
    /**
     * Promise of `true` if the given account has already executed a lock
     */
    getAccountHasLocked(lockerAddress) {
        if (!lockerAddress) {
            throw new Error("lockerAddress is not defined");
        }
        this.logContractFunctionCall("ExternalLocking4Reputation.externalLockers");
        return this.contract.externalLockers(lockerAddress);
    }
}
exports.ExternalLocking4ReputationWrapper = ExternalLocking4ReputationWrapper;
class ExternalLocking4ReputationType extends contractWrapperFactory_1.ContractWrapperFactory {
    deployed() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            throw new Error("ExternalLocking4Reputation has not been deployed");
        });
    }
}
exports.ExternalLocking4ReputationType = ExternalLocking4ReputationType;
exports.ExternalLocking4ReputationFactory = new ExternalLocking4ReputationType("ExternalLocking4Reputation", ExternalLocking4ReputationWrapper, new web3EventService_1.Web3EventService());
//# sourceMappingURL=externalLocking4Reputation.js.map