"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const __1 = require("..");
const byzcoin_rpc_1 = require("../byzcoin-rpc");
const instance_1 = tslib_1.__importDefault(require("../instance"));
class ValueInstance extends instance_1.default {
    /**
     * Constructs a new ValueInstance. If the instance is not of type ValueInstance,
     * an error will be thrown.
     *
     * @param rpc a working RPC instance
     * @param inst an instance representing a ValueInstance
     */
    constructor(rpc, inst) {
        super(inst);
        this.rpc = rpc;
        if (inst.contractID.toString() !== ValueInstance.contractID) {
            throw new Error(`mismatch contract name: ${inst.contractID} vs ${ValueInstance.contractID}`);
        }
        this._value = this.data;
    }
    /**
     * Spawn a value instance from a darc id
     *
     * @param bc        The RPC to use
     * @param darcID    The darc instance ID
     * @param signers   The list of signers for the transaction
     * @param value     The value to be put in the value instance
     * @param preID     Can be used to set the InstanceID of the value
     * @returns a promise that resolves with the new instance
     */
    static spawn(bc, darcID, signers, value, preID) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const inst = __1.Instruction.createSpawn(darcID, ValueInstance.contractID, [new __1.Argument({ name: ValueInstance.argumentValue, value })]);
            if (preID && bc.getProtocolVersion() >= byzcoin_rpc_1.versionPreID) {
                inst.spawn.args.push(new __1.Argument({ name: "preID", value: preID }));
            }
            yield inst.updateCounters(bc, signers);
            const ctx = __1.ClientTransaction.make(bc.getProtocolVersion(), inst);
            ctx.signWith([signers]);
            yield bc.sendTransactionAndWait(ctx, 10);
            return ValueInstance.fromByzcoin(bc, ctx.instructions[0].deriveId(), 1);
        });
    }
    /**
     * Create returns a ValueInstance from the given parameters.
     * @param bc
     * @param valueID
     * @param darcID
     * @param value
     */
    static create(bc, valueID, darcID, value) {
        return new ValueInstance(bc, new instance_1.default({
            contractID: ValueInstance.contractID,
            darcID,
            data: value,
            id: valueID,
        }));
    }
    /**
     * Initializes using an existing ValueInstance from ByzCoin
     * @param bc    The RPC to use
     * @param iid   The instance ID
     * @param waitMatch how many times to wait for a match - useful if its called just after an addTransactionAndWait.
     * @param interval how long to wait between two attempts in waitMatch.
     * @returns a promise that resolves with the coin instance
     */
    static fromByzcoin(bc, iid, waitMatch = 0, interval = 1000) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return new ValueInstance(bc, yield instance_1.default.fromByzcoin(bc, iid, waitMatch, interval));
        });
    }
    /**
     * @return value of the instance
     */
    get value() {
        return this._value;
    }
    /**
     * Update the value
     *
     * @param signers   The list of signers for the transaction
     * @param value     The new value to be set
     * @param wait      Number of blocks to wait for inclusion
     */
    updateValue(signers, value, wait) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const inst = __1.Instruction.createInvoke(this.id, ValueInstance.contractID, ValueInstance.commandUpdate, [new __1.Argument({ name: ValueInstance.argumentValue, value })]);
            yield inst.updateCounters(this.rpc, signers);
            const ctx = __1.ClientTransaction.make(this.rpc.getProtocolVersion(), inst);
            ctx.signWith([signers]);
            yield this.rpc.sendTransactionAndWait(ctx, wait);
        });
    }
    /**
     * Update the data of this instance
     *
     * @returns the updated instance
     */
    update() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const p = yield this.rpc.getProofFromLatest(this.id);
            if (!p.exists(this.id)) {
                throw new Error("fail to get a matching proof");
            }
            this._value = p.value;
            return this;
        });
    }
}
exports.default = ValueInstance;
ValueInstance.contractID = "value";
ValueInstance.commandUpdate = "update";
ValueInstance.argumentValue = "value";
