"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const ajv = require("ajv");
const TagsRule_1 = require("../../../rules/TagsRule");
const AuthorsRule_1 = require("../../../rules/AuthorsRule");
const CustomRPCRule_1 = require("../../../rules/CustomRPCRule");
const SteemOperationNumber_1 = require("../../../blockchain/SteemOperationNumber");
const WeightRule_1 = require("../../../rules/WeightRule");
const aajv = new ajv();
aajv.addMetaSchema(require("ajv/lib/refs/json-schema-draft-06.json"));
const validate = aajv.compile(require("./smartvotes.schema.json"));
class V1Handler {
    handleOrReject(transaction) {
        if (transaction.block_num > 22710498)
            return undefined; // this protocol version is disabled for new transactions
        if (transaction.ops[0][0] != "custom_json" || transaction.ops[0][1].id != "smartvote")
            return undefined;
        if (transaction.ops[0][1].required_posting_auths.length != 1)
            return undefined; // must be authorized by single user
        const jsonObj = JSON.parse(transaction.ops[0][1].json);
        if (!this.validateJSON(jsonObj))
            return undefined;
        const smartvotesOp = jsonObj;
        return this.transform(transaction, smartvotesOp, transaction.ops[0][1].required_posting_auths[0]);
    }
    validateJSON(input) {
        return validate(input);
    }
    transform(op, smartvotesOp, sender) {
        if (smartvotesOp.name == "set_rules") { // sort for every voter
            return this.transformSetRules(op, smartvotesOp, sender);
        }
        else if (smartvotesOp.name == "send_voteorder") {
            return this.transformSendVoteorder(op, smartvotesOp, sender);
        }
        else if (smartvotesOp.name == "confirm_votes") {
            return this.transformConfirmVotes(op, smartvotesOp, sender);
        }
        else
            return undefined;
    }
    transformSetRules(op, smartvotesOp, sender) {
        const rulesPerVoter = [];
        for (let i = 0; i < smartvotesOp.rulesets.length; i++) {
            const ruleset = smartvotesOp.rulesets[i];
            let create = true;
            for (let j = 0; j < rulesPerVoter.length; j++) {
                if (rulesPerVoter[j][0] === ruleset.voter) {
                    rulesPerVoter[j][1].push(this.transformRuleset(ruleset));
                    create = false;
                }
            }
            if (create) {
                rulesPerVoter.push([ruleset.voter, [this.transformRuleset(ruleset)]]);
            }
        }
        const out = [];
        for (let i = 0; i < rulesPerVoter.length; i++) {
            const cmd = {
                rulesets: rulesPerVoter[i][1]
            };
            out.push({
                moment: new SteemOperationNumber_1.SteemOperationNumber(op.block_num, op.transaction_num),
                transaction_id: op.transaction_id,
                timestamp: op.timestamp,
                voter: rulesPerVoter[i][0],
                delegator: sender,
                command: cmd
            });
        }
        return out;
    }
    transformRuleset(ruleset) {
        const rules = [];
        for (let i = 0; i < ruleset.rules.length; i++) {
            const rule = ruleset.rules[i];
            if (rule.type === "tags") {
                if (rule.mode === "allow")
                    rules.push(new TagsRule_1.TagsRule(TagsRule_1.TagsRule.Mode.ALLOW, rule.tags));
                else if (rule.mode === "deny")
                    rules.push(new TagsRule_1.TagsRule(TagsRule_1.TagsRule.Mode.DENY, rule.tags));
                else if (rule.mode === "require")
                    rules.push(new TagsRule_1.TagsRule(TagsRule_1.TagsRule.Mode.REQUIRE, rule.tags));
                else if (rule.mode === "any")
                    rules.push(new TagsRule_1.TagsRule(TagsRule_1.TagsRule.Mode.ANY, rule.tags));
            }
            else if (rule.type === "authors") {
                if (rule.mode === "allow")
                    rules.push(new AuthorsRule_1.AuthorsRule(AuthorsRule_1.AuthorsRule.Mode.ALLOW, rule.authors));
                else if (rule.mode === "deny")
                    rules.push(new AuthorsRule_1.AuthorsRule(AuthorsRule_1.AuthorsRule.Mode.DENY, rule.authors));
            }
            else if (rule.type === "custom_rpc") {
                rules.push(new CustomRPCRule_1.CustomRPCRule(rule.rpc_host, rule.rpc_port, rule.rpc_path, rule.rpc_method));
            }
        }
        rules.push(new WeightRule_1.WeightRule(
        /*min: */ (ruleset.action == "flag" || ruleset.action == "upvote+flag") ? (-1 * ruleset.total_weight) : 0, 
        /*max: */ (ruleset.action == "upvote" || ruleset.action == "upvote+flag") ? (1 * ruleset.total_weight) : 0));
        return { name: ruleset.name, rules: rules };
    }
    transformSendVoteorder(op, smartvotesOp, sender) {
        const cmd = {
            rulesetName: smartvotesOp.voteorder.ruleset_name,
            permlink: smartvotesOp.voteorder.permlink,
            author: smartvotesOp.voteorder.author,
            weight: smartvotesOp.voteorder.weight * (smartvotesOp.voteorder.type == "flag" ? -1 : 1)
        };
        return [{
                moment: new SteemOperationNumber_1.SteemOperationNumber(op.block_num, op.transaction_num),
                transaction_id: op.transaction_id,
                timestamp: op.timestamp,
                voter: sender,
                delegator: smartvotesOp.voteorder.delegator,
                command: cmd
            }];
    }
    transformConfirmVotes(op, smartvotesOp, sender) {
        const out = [];
        for (let i = 0; i < smartvotesOp.voteorders.length; i++) {
            const confirmation = smartvotesOp.voteorders[i];
            const cmd = {
                voteorderTxId: confirmation.transaction_id,
                accepted: !confirmation.invalid,
                msg: ""
            };
            out.push({
                moment: new SteemOperationNumber_1.SteemOperationNumber(op.block_num, op.transaction_num),
                transaction_id: op.transaction_id,
                timestamp: op.timestamp,
                voter: "unknown",
                delegator: sender,
                command: cmd
            });
        }
        return out;
    }
    serializeToBlockchain(op) {
        throw new Error("Protocol version V1 is disabled");
    }
}
V1Handler.INTRODUCTION_OF_WISE_MOMENT = new SteemOperationNumber_1.SteemOperationNumber(21622860, 26, 0);
exports.V1Handler = V1Handler;
//# sourceMappingURL=V1Handler.js.map