"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.Claims = void 0;
const lodash_1 = require("lodash");
const internal_1 = require("./internal");
const queries_1 = require("./middleware/queries");
const types_1 = require("./middleware/types");
const types_2 = require("./types");
const internal_2 = require("./types/internal");
const conversion_1 = require("./utils/conversion");
const internal_3 = require("./utils/internal");
/**
 * Handles all Claims related functionality
 */
class Claims {
    /**
     * @hidden
     */
    constructor(context) {
        this.context = context;
        this.addClaims = internal_3.createProcedureMethod({
            getProcedureAndArgs: args => [
                internal_1.modifyClaims,
                Object.assign(Object.assign({}, args), { operation: internal_2.ClaimOperation.Add }),
            ],
        }, context);
        this.editClaims = internal_3.createProcedureMethod({
            getProcedureAndArgs: args => [
                internal_1.modifyClaims,
                Object.assign(Object.assign({}, args), { operation: internal_2.ClaimOperation.Edit }),
            ],
        }, context);
        this.revokeClaims = internal_3.createProcedureMethod({
            getProcedureAndArgs: args => [
                internal_1.modifyClaims,
                Object.assign(Object.assign({}, args), { operation: internal_2.ClaimOperation.Revoke }),
            ],
        }, context);
        this.addInvestorUniquenessClaim = internal_3.createProcedureMethod({ getProcedureAndArgs: args => [internal_1.addInvestorUniquenessClaim, args] }, context);
    }
    /**
     * Retrieve all claims issued by an Identity
     *
     * @param opts.target - identity (optional, defaults to the current Identity)
     * @param opts.includeExpired - whether to include expired claims. Defaults to true
     *
     * @note supports pagination
     * @note uses the middleware
     */
    getIssuedClaims(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const { context } = this;
            const { target, includeExpired = true, size, start } = opts;
            const did = yield internal_3.getDid(target, context);
            return context.getIdentityClaimsFromMiddleware({
                trustedClaimIssuers: [did],
                includeExpired,
                size,
                start,
            });
        });
    }
    /**
     * Retrieve a list of Identities with claims associated to them. Can be filtered using parameters
     *
     * @param opts.targets - identities (or Identity IDs) for which to fetch claims (targets). Defaults to all targets
     * @param opts.trustedClaimIssuers - identity IDs of claim issuers. Defaults to all claim issuers
     * @param opts.scope - scope of the claims to fetch. Defaults to any scope
     * @param opts.claimTypes - types of the claims to fetch. Defaults to any type
     * @param opts.includeExpired - whether to include expired claims. Defaults to true
     * @param opts.size - page size
     * @param opts.start - page offset
     *
     * @note supports pagination
     * @note uses the middleware
     */
    getIdentitiesWithClaims(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const { context } = this;
            const { targets, trustedClaimIssuers, scope, claimTypes, includeExpired = true, size, start, } = opts;
            const result = yield context.queryMiddleware(queries_1.didsWithClaims({
                dids: targets === null || targets === void 0 ? void 0 : targets.map(target => conversion_1.signerToString(target)),
                scope: scope ? conversion_1.scopeToMiddlewareScope(scope) : undefined,
                trustedClaimIssuers: trustedClaimIssuers === null || trustedClaimIssuers === void 0 ? void 0 : trustedClaimIssuers.map(trustedClaimIssuer => conversion_1.signerToString(trustedClaimIssuer)),
                claimTypes: claimTypes === null || claimTypes === void 0 ? void 0 : claimTypes.map(ct => types_1.ClaimTypeEnum[ct]),
                includeExpired,
                count: size,
                skip: start,
            }));
            const { data: { didsWithClaims: { items: didsWithClaimsList, totalCount: count }, }, } = result;
            const data = conversion_1.toIdentityWithClaimsArray(didsWithClaimsList, context);
            const next = internal_3.calculateNextKey(count, size, start);
            return {
                data,
                next,
                count,
            };
        });
    }
    /**
     * Retrieve all scopes in which claims have been made for the target Identity.
     *   If the scope is an asset DID, the corresponding ticker is returned as well
     *
     * @param opts.target - identity for which to fetch claim scopes (optional, defaults to the current Identity)
     */
    getClaimScopes(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const { context } = this;
            const { target } = opts;
            const did = yield internal_3.getDid(target, context);
            const identityClaimsFromChain = yield context.getIdentityClaimsFromChain({
                targets: [did],
                claimTypes: [
                    types_2.ClaimType.Accredited,
                    types_2.ClaimType.Affiliate,
                    types_2.ClaimType.Blocked,
                    types_2.ClaimType.BuyLockup,
                    types_2.ClaimType.Exempted,
                    types_2.ClaimType.InvestorUniqueness,
                    types_2.ClaimType.Jurisdiction,
                    types_2.ClaimType.KnowYourCustomer,
                    types_2.ClaimType.SellLockup,
                ],
                trustedClaimIssuers: undefined,
                includeExpired: true,
            });
            const claimScopeList = identityClaimsFromChain.map(({ claim }) => {
                // only Scoped Claims were fetched so this assertion is reasonable
                const { scope: { type, value }, } = claim;
                let ticker;
                if (type === types_2.ScopeType.Ticker) {
                    ticker = internal_3.removePadding(value);
                }
                return {
                    scope: { type, value: ticker !== null && ticker !== void 0 ? ticker : value },
                    ticker,
                };
            });
            return lodash_1.uniqWith(claimScopeList, lodash_1.isEqual);
        });
    }
    /**
     * Retrieve the list of CDD claims for a target Identity
     *
     * @param opts.target - identity for which to fetch CDD claims (optional, defaults to the current Identity)
     * @param opts.includeExpired - whether to include expired claims. Defaults to true
     */
    getCddClaims(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const { context } = this;
            const { target, includeExpired = true } = opts;
            const did = yield internal_3.getDid(target, context);
            return context.getIdentityClaimsFromChain({
                targets: [did],
                claimTypes: [types_2.ClaimType.CustomerDueDiligence],
                includeExpired,
            });
        });
    }
    /**
     * Retrieve the list of InvestorUniqueness claims for a target Identity
     *
     * @param opts.target - identity for which to fetch CDD claims (optional, defaults to the current Identity)
     * @param opts.includeExpired - whether to include expired claims. Defaults to true
     */
    getInvestorUniquenessClaims(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const { context } = this;
            const { target, includeExpired = true } = opts;
            const did = yield internal_3.getDid(target, context);
            return context.getIdentityClaimsFromChain({
                targets: [did],
                claimTypes: [types_2.ClaimType.InvestorUniqueness],
                includeExpired,
            });
        });
    }
    /**
     * Retrieve all claims issued about an Identity, grouped by claim issuer
     *
     * @param opts.target - identity for which to fetch targeting claims (optional, defaults to the current Identity)
     * @param opts.includeExpired - whether to include expired claims. Defaults to true
     *
     * @note supports pagination
     * @note uses the middleware (optional)
     */
    getTargetingClaims(opts = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            const { context } = this;
            const { target, trustedClaimIssuers, scope, includeExpired = true, size, start } = opts;
            const did = yield internal_3.getDid(target, context);
            const isMiddlewareAvailable = yield context.isMiddlewareAvailable();
            if (isMiddlewareAvailable) {
                const result = yield context.queryMiddleware(queries_1.issuerDidsWithClaimsByTarget({
                    target: did,
                    scope: scope ? conversion_1.scopeToMiddlewareScope(scope) : undefined,
                    trustedClaimIssuers: trustedClaimIssuers === null || trustedClaimIssuers === void 0 ? void 0 : trustedClaimIssuers.map(trustedClaimIssuer => conversion_1.signerToString(trustedClaimIssuer)),
                    includeExpired,
                    count: size,
                    skip: start,
                }));
                const { data: { issuerDidsWithClaimsByTarget: { items: issuerDidsWithClaimsByTargetList, totalCount: count, }, }, } = result;
                const data = conversion_1.toIdentityWithClaimsArray(issuerDidsWithClaimsByTargetList, context);
                const next = internal_3.calculateNextKey(count, size, start);
                return {
                    data,
                    next,
                    count,
                };
            }
            const identityClaimsFromChain = yield context.getIdentityClaimsFromChain({
                targets: [did],
                trustedClaimIssuers: trustedClaimIssuers === null || trustedClaimIssuers === void 0 ? void 0 : trustedClaimIssuers.map(trustedClaimIssuer => conversion_1.signerToString(trustedClaimIssuer)),
                includeExpired,
            });
            const issuers = lodash_1.uniqBy(identityClaimsFromChain.map(i => i.issuer), identity => identity.did);
            const identitiesWithClaims = issuers.map(identity => {
                return {
                    identity,
                    claims: lodash_1.filter(identityClaimsFromChain, ({ issuer: { did: issuerDid } }) => issuerDid === identity.did),
                };
            });
            return {
                data: identitiesWithClaims,
                next: null,
                count: identitiesWithClaims.length,
            };
        });
    }
}
exports.Claims = Claims;
//# sourceMappingURL=Claims.js.map