"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const ajv = require("ajv");
const SendVoteorder_1 = require("../../SendVoteorder");
const SetRules_1 = require("../../SetRules");
const SteemOperationNumber_1 = require("../../../blockchain/SteemOperationNumber");
const ConfirmVote_1 = require("../../ConfirmVote");
const rules_schema_1 = require("./rules-schema");
const VoteOperation_1 = require("../../../blockchain/VoteOperation");
class WiseConstants {
}
WiseConstants.wise_send_voteorder_descriptor = "v2:send_voteorder";
WiseConstants.wise_set_rules_descriptor = "v2:set_rules";
WiseConstants.wise_confirm_vote_descriptor = "v2:confirm_vote";
WiseConstants.wise_descriptors = [
    WiseConstants.wise_send_voteorder_descriptor,
    WiseConstants.wise_set_rules_descriptor,
    WiseConstants.wise_confirm_vote_descriptor
];
const aajv = new ajv();
aajv.addMetaSchema(require("ajv/lib/refs/json-schema-draft-06.json"));
const validate = aajv.compile(require("./wise-schema.json"));
class V2Handler {
    constructor() {
        this.handleOrReject = (transaction) => {
            if (transaction.block_num <= 22710498)
                return undefined;
            let wiseCustomJsonOp = undefined;
            transaction.ops.forEach(op => {
                if (op[0] != "custom_json" || op[1].id != V2Handler.CUSTOM_JSON_ID) {
                    return undefined;
                }
                if (op[1].required_posting_auths.length != 1) {
                    return undefined; // must be authorized by single user
                }
                if (!this.isMyOperation(op[1].json)) {
                    return undefined;
                }
                if (!wiseCustomJsonOp)
                    wiseCustomJsonOp = op[1];
            });
            if (wiseCustomJsonOp) {
                const wiseCustomJsonOp_ = wiseCustomJsonOp; // allow ts compiler resolve types properly
                const jsonObj = JSON.parse(wiseCustomJsonOp_.json);
                if (!this.validateJSON(jsonObj)) {
                    return undefined;
                }
                const wiseOp = jsonObj;
                return this.decode(transaction, wiseOp, wiseCustomJsonOp_.required_posting_auths[0]);
            }
            else {
                return undefined;
            }
        };
        this.isMyOperation = (jsonStr) => {
            const descriptorStart = jsonStr.indexOf("\"") + 1;
            const descriptor = jsonStr.substring(descriptorStart, jsonStr.indexOf("\"", descriptorStart));
            return WiseConstants.wise_descriptors.indexOf(descriptor) !== -1;
        };
        this.validateJSON = (input) => {
            return validate(input);
        };
        this.decode = (transaction, wiseOp, sender) => {
            if (wiseOp[0] == WiseConstants.wise_confirm_vote_descriptor) {
                return this.decodeConfirmVote(transaction, wiseOp, sender);
            }
            if (wiseOp[0] == WiseConstants.wise_set_rules_descriptor) {
                return this.decodeSetRules(transaction, wiseOp, sender);
            }
            else if (wiseOp[0] == WiseConstants.wise_send_voteorder_descriptor) {
                return this.decodeSendVoteorder(transaction, wiseOp, sender);
            }
            else
                return undefined;
        };
        this.decodeSetRules = (transaction, wiseOp, sender) => {
            const rulesets = [];
            for (let i = 0; i < wiseOp[1].rulesets.length; i++) {
                const ruleset = wiseOp[1].rulesets[i];
                rulesets.push(this.decodeRuleset(ruleset));
            }
            const out = {
                moment: new SteemOperationNumber_1.SteemOperationNumber(transaction.block_num, transaction.transaction_num, 0 /* skip operation num due to rejection that was done in #handleOrReject */),
                transaction_id: transaction.transaction_id,
                timestamp: transaction.timestamp,
                voter: wiseOp[1].voter,
                delegator: sender,
                command: {
                    rulesets: rulesets
                }
            };
            return [out];
        };
        this.decodeRuleset = (ruleset) => {
            const rules = [];
            for (let i = 0; i < ruleset[1].length; i++) {
                const rule = ruleset[1][i];
                const decodeed = rules_schema_1.wise_rule_decode(rule);
                if (decodeed)
                    rules.push(decodeed);
            }
            return { name: ruleset[0], rules };
        };
        this.decodeSendVoteorder = (transaction, wiseOp, sender) => {
            const cmd = {
                rulesetName: wiseOp[1].ruleset,
                permlink: wiseOp[1].permlink,
                author: wiseOp[1].author,
                weight: wiseOp[1].weight
            };
            return [{
                    moment: new SteemOperationNumber_1.SteemOperationNumber(transaction.block_num, transaction.transaction_num, 0 /* skip operation num due to rejection that was done in #handleOrReject */),
                    transaction_id: transaction.transaction_id,
                    timestamp: transaction.timestamp,
                    voter: sender,
                    delegator: wiseOp[1].delegator,
                    command: cmd
                }];
        };
        this.decodeConfirmVote = (transaction, wiseOp, sender) => {
            let voteOp = undefined;
            if (transaction.ops.length > 1) {
                transaction.ops.forEach((op) => {
                    const potentialVoteOp = op[1];
                    if (VoteOperation_1.VoteOperation.isVoteOperation(potentialVoteOp)) {
                        if (!voteOp)
                            voteOp = potentialVoteOp;
                    }
                });
            }
            let cmd;
            if (voteOp) {
                const cmd_ = {
                    voteorderTxId: wiseOp[1].tx_id,
                    accepted: wiseOp[1].accepted,
                    msg: wiseOp[1].msg,
                    vote: voteOp,
                };
                cmd = cmd_;
            }
            else {
                const cmd_ = {
                    voteorderTxId: wiseOp[1].tx_id,
                    accepted: wiseOp[1].accepted,
                    msg: wiseOp[1].msg,
                };
                cmd = cmd_;
            }
            return [{
                    moment: new SteemOperationNumber_1.SteemOperationNumber(transaction.block_num, transaction.transaction_num, 0 /* skip operation num due to rejection that was done in #handleOrReject */),
                    transaction_id: transaction.transaction_id,
                    timestamp: transaction.timestamp,
                    voter: wiseOp[1].voter,
                    delegator: sender,
                    command: cmd
                }];
        };
        this.serializeToBlockchain = (op) => {
            let senderUsername = "";
            let jsonObj;
            if (SetRules_1.SetRules.isSetRules(op.command)) {
                senderUsername = op.delegator;
                const rulesets = [];
                for (let i = 0; i < op.command.rulesets.length; i++) {
                    const ruleset = op.command.rulesets[i];
                    rulesets.push(this.serializeRuleset(ruleset));
                }
                jsonObj = ["v2:set_rules", {
                        voter: op.voter,
                        rulesets: rulesets
                    }];
            }
            else if (SendVoteorder_1.SendVoteorder.isSendVoteorder(op.command)) {
                senderUsername = op.voter;
                jsonObj = ["v2:send_voteorder", {
                        delegator: op.delegator,
                        ruleset: op.command.rulesetName,
                        author: op.command.author,
                        permlink: op.command.permlink,
                        weight: op.command.weight
                    }];
            }
            else if (ConfirmVote_1.ConfirmVote.isConfirmVote(op.command)) {
                senderUsername = op.delegator;
                jsonObj = ["v2:confirm_vote", {
                        voter: op.voter,
                        tx_id: op.command.voteorderTxId,
                        accepted: op.command.accepted,
                        msg: op.command.msg
                    }];
            }
            else
                throw new Error("Unknown type of command");
            const completeOp = ["custom_json", {
                    id: V2Handler.CUSTOM_JSON_ID,
                    json: JSON.stringify(jsonObj),
                    required_auths: [],
                    required_posting_auths: [senderUsername]
                }];
            validate(completeOp);
            return [completeOp];
        };
        this.serializeRuleset = (r) => {
            const out = [];
            for (let i = 0; i < r.rules.length; i++) {
                const rule = r.rules[i];
                out.push(rules_schema_1.wise_rule_encode(rule));
            }
            return [r.name, out];
        };
    }
}
V2Handler.CUSTOM_JSON_ID = "wise";
exports.V2Handler = V2Handler;
//# sourceMappingURL=V2Handler.js.map