"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const token_math_1 = require("@melonproject/token-math");
const getPoliciesBySig_1 = require("./getPoliciesBySig");
const identifier_1 = require("./identifier");
const maxConcentration_1 = require("./maxConcentration");
const maxPositions_1 = require("./maxPositions");
const getMembers_1 = require("./getMembers");
const tolerance_1 = require("./tolerance");
const FunctionSignatures_1 = require("../../trading/utils/FunctionSignatures");
const getTokenByAddress_1 = require("../../../../utils/environment/getTokenByAddress");
const web3_utils_1 = __importDefault(require("web3-utils"));
// manually defining cases for each policy that has params
const getParametersForPolicy = (env, policyName, policyAddress) => __awaiter(this, void 0, void 0, function* () {
    switch (policyName) {
        case 'Max concentration': {
            const value = yield maxConcentration_1.maxConcentration(env, policyAddress);
            const quantity = token_math_1.createQuantity({
                decimals: 18,
                symbol: 'NONE',
            }, value);
            return `${parseFloat(token_math_1.toFixed(quantity)) * 100}%`;
        }
        case 'Max positions': {
            const value = yield maxPositions_1.maxPositions(env, policyAddress);
            return `${value}`;
        }
        case 'Price tolerance': {
            const value = yield tolerance_1.tolerance(env, policyAddress);
            const quantity = token_math_1.createQuantity({
                decimals: 18,
                symbol: 'NONE',
            }, value);
            return `${parseFloat(token_math_1.toFixed(quantity)) * 100}%`;
        }
        case 'Asset whitelist': {
            const members = yield getMembers_1.getMembers(env, policyAddress);
            const symbols = members
                .map(address => getTokenByAddress_1.getTokenByAddress(env, address))
                .map(token => token.symbol);
            return symbols.join(', ');
        }
        case 'Asset blacklist': {
            const members = yield getMembers_1.getMembers(env, policyAddress);
            const symbols = members
                .map(address => getTokenByAddress_1.getTokenByAddress(env, address))
                .map(token => token.symbol);
            return symbols.join(', ');
        }
        default:
            return null;
    }
});
const getFunctionIdentifier = (env, functionNameAndArguments) => {
    return web3_utils_1.default.keccak256(functionNameAndArguments).slice(0, 10);
};
exports.getPolicyInformation = (env, policyManager) => __awaiter(this, void 0, void 0, function* () {
    // HACK: uses a heuristic to check most common signatures
    const sigsToCheck = [
        getFunctionIdentifier(env, FunctionSignatures_1.FunctionSignatures.makeOrder),
        getFunctionIdentifier(env, FunctionSignatures_1.FunctionSignatures.takeOrder),
        getFunctionIdentifier(env, FunctionSignatures_1.FunctionSignatures.cancelOrder),
        getFunctionIdentifier(env, FunctionSignatures_1.FunctionSignatures.withdrawTokens),
        getFunctionIdentifier(env, FunctionSignatures_1.FunctionSignatures.requestInvestment),
    ];
    const retrievedPolicies = yield Promise.all(sigsToCheck.map(sig => {
        return getPoliciesBySig_1.getPoliciesBySig(env, policyManager, { sig });
    }));
    const policyAddresses = retrievedPolicies.map(policy => {
        return [...policy.pre, ...policy.post].map(address => address.toString());
    });
    const uniquePolicyAddresses = policyAddresses.reduce((carry, current) => {
        const add = current.filter(address => carry.indexOf(address) === -1);
        return [...carry, ...add];
    }, []);
    const policyObjects = uniquePolicyAddresses.map((address) => __awaiter(this, void 0, void 0, function* () {
        const name = yield identifier_1.identifier(env, address);
        const parameters = yield getParametersForPolicy(env, name, address);
        return {
            address,
            name,
            parameters,
        };
    }));
    return Promise.all(policyObjects);
});
