"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    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) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setPermissionGroup = exports.prepareStorage = exports.getAuthorization = exports.prepareSetPermissionGroup = void 0;
const types_1 = require("../../polkadot/types");
const utils_1 = require("./utils");
const internal_1 = require("../../internal");
const types_2 = require("../../types");
const conversion_1 = require("../../utils/conversion");
const internal_2 = require("../../utils/internal");
/**
 * @hidden
 */
const agentGroupResolver = (group, context) => conversion_1.permissionGroupIdentifierToAgentGroup(group instanceof internal_1.CustomPermissionGroup ? { custom: group.id } : group.type, context);
/**
 * @hidden
 */
function prepareSetPermissionGroup(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const { context: { polymeshApi: { tx: { externalAgents }, }, }, context, storage: { token }, } = this;
        const { identity, group } = args;
        const { ticker } = token;
        const { did } = identity;
        const [currentGroup, currentAgents] = yield Promise.all([
            identity.tokenPermissions.getGroup({ token }),
            token.permissions.getAgents(),
        ]);
        if (utils_1.isFullGroupType(currentGroup)) {
            const fullGroupAgents = currentAgents.filter(({ group: groupOfAgent }) => utils_1.isFullGroupType(groupOfAgent));
            if (fullGroupAgents.length === 1) {
                throw new internal_1.PolymeshError({
                    code: types_2.ErrorCode.ValidationError,
                    message: 'The target is the last Agent with full permissions for this Security Token. There should always be at least one Agent with full permissions',
                });
            }
        }
        if (!currentAgents.find(({ agent }) => agent.did === did)) {
            throw new internal_1.PolymeshError({
                code: types_2.ErrorCode.ValidationError,
                message: 'The target must already be an Agent for the Security Token',
            });
        }
        let returnValue;
        let rawAgentGroup;
        if (!types_2.isEntity(group)) {
            returnValue = yield this.addProcedure(internal_1.createGroup(), {
                ticker,
                permissions: group,
            });
            rawAgentGroup = returnValue.transform(customPermissionGroup => agentGroupResolver(customPermissionGroup, context));
        }
        else {
            if (group.isEqual(currentGroup)) {
                throw new internal_1.PolymeshError({
                    code: types_2.ErrorCode.ValidationError,
                    message: 'The Agent is already part of this permission group',
                });
            }
            returnValue = group;
            rawAgentGroup = agentGroupResolver(group, context);
        }
        const rawTicker = conversion_1.stringToTicker(ticker, context);
        const rawIdentityId = conversion_1.stringToIdentityId(did, context);
        this.addTransaction(externalAgents.changeGroup, {}, rawTicker, rawIdentityId, rawAgentGroup);
        return returnValue;
    });
}
exports.prepareSetPermissionGroup = prepareSetPermissionGroup;
/**
 * @hidden
 */
function getAuthorization() {
    const { storage: { token }, } = this;
    return {
        permissions: {
            transactions: [types_1.TxTags.externalAgents.ChangeGroup],
            tokens: [token],
            portfolios: [],
        },
    };
}
exports.getAuthorization = getAuthorization;
/**
 * @hidden
 */
function prepareStorage({ group }) {
    const { context } = this;
    let token;
    if (types_2.isEntity(group)) {
        ({ ticker: token } = group);
    }
    else {
        ({ token } = group);
    }
    return {
        token: internal_2.getToken(token, context),
    };
}
exports.prepareStorage = prepareStorage;
/**
 * @hidden
 */
const setPermissionGroup = () => new internal_1.Procedure(prepareSetPermissionGroup, getAuthorization, prepareStorage);
exports.setPermissionGroup = setPermissionGroup;
//# sourceMappingURL=setPermissionGroup.js.map