"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
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());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RegistryPositionSource = void 0;
const common_1 = require("@nestjs/common");
const config_1 = require("@nestjs/config");
const file_system_cache_1 = __importDefault(require("file-system-cache"));
const lodash_1 = require("lodash");
const contract_interface_1 = require("../../position/contract.interface");
const position_fetcher_registry_1 = require("../../position/position-fetcher.registry");
let RegistryPositionSource = class RegistryPositionSource {
    constructor(configService, positionFetcherRegistry) {
        this.configService = configService;
        this.positionFetcherRegistry = positionFetcherRegistry;
        this.cacheManager = (0, file_system_cache_1.default)({
            basePath: './.cache',
            ns: '@CacheOnInterval',
        });
    }
    getApiResolvedPositions() {
        var _a;
        return (_a = this.configService.get('apiResolvedPositions')) !== null && _a !== void 0 ? _a : [];
    }
    getTokenDependenciesBatch(queries) {
        return __awaiter(this, void 0, void 0, function* () {
            const networks = (0, lodash_1.uniq)(queries.map(query => query.network));
            const groups = this.positionFetcherRegistry.getRegisteredTokenGroups();
            const networkGroups = groups.filter(({ network }) => networks.includes(network));
            const cacheKeys = networkGroups.map(group => (0, position_fetcher_registry_1.buildAppPositionsCacheKey)(Object.assign({ type: contract_interface_1.ContractType.APP_TOKEN }, group)));
            const cachedTokenResults = yield Promise.all((0, lodash_1.uniq)(cacheKeys).map((key) => __awaiter(this, void 0, void 0, function* () {
                var _a;
                const cachedData = yield this.cacheManager.get(key);
                return (_a = cachedData) !== null && _a !== void 0 ? _a : [];
            })));
            const allTokens = cachedTokenResults.flat();
            return queries.map(q => {
                var _a;
                return (_a = allTokens.find(t => {
                    const isNetworkMatch = t.network === q.network;
                    const isAddressMatch = t.address === q.address;
                    const isMaybeTokenIdMatch = !q.tokenId || q.tokenId === t.dataProps.tokenId;
                    return isNetworkMatch && isAddressMatch && isMaybeTokenIdMatch;
                })) !== null && _a !== void 0 ? _a : null;
            });
        });
    }
    getSupported(definitions, contractType) {
        const defs = definitions.flatMap(({ appId, groupIds, network }) => groupIds.map(groupId => {
            const def = { appId, groupId, network, contractType };
            try {
                this.positionFetcherRegistry.get({ type: contractType, appId, groupId, network });
                const isLocallyProvided = !this.getApiResolvedPositions().includes(appId);
                return Object.assign(Object.assign({}, def), { supported: isLocallyProvided });
            }
            catch (e) {
                return Object.assign(Object.assign({}, def), { supported: false });
            }
        }));
        const partionedDefs = (0, lodash_1.partition)(defs, def => def.supported);
        const [supported, unsupported] = partionedDefs.map(partition => {
            const grouped = (0, lodash_1.groupBy)(partition, ({ appId, contractType, network }) => [appId, contractType, network].join(':'));
            return (0, lodash_1.map)(grouped, group => {
                const def = group[0];
                return {
                    appId: def.appId,
                    network: def.network,
                    contractType: def.contractType,
                    groupIds: group.map(({ groupId }) => groupId),
                };
            });
        });
        return { supported, unsupported };
    }
    getPositions(definitions, contractType) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!definitions.length)
                return [];
            const fetchers = definitions.flatMap(({ appId, groupIds, network }) => groupIds.map(groupId => {
                try {
                    return this.positionFetcherRegistry.get({ type: contractType, appId, groupId, network });
                }
                catch (e) {
                    return null;
                }
            }));
            const validFetchers = (0, lodash_1.compact)(fetchers);
            const positions = (yield Promise.all(validFetchers.map((fetcher) => __awaiter(this, void 0, void 0, function* () { var _a; return (_a = (yield fetcher.getPositions())) !== null && _a !== void 0 ? _a : []; }))));
            return positions.flat();
        });
    }
};
RegistryPositionSource = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, common_1.Inject)(config_1.ConfigService)),
    __param(1, (0, common_1.Inject)(position_fetcher_registry_1.PositionFetcherRegistry)),
    __metadata("design:paramtypes", [config_1.ConfigService,
        position_fetcher_registry_1.PositionFetcherRegistry])
], RegistryPositionSource);
exports.RegistryPositionSource = RegistryPositionSource;
//# sourceMappingURL=position-source.registry.js.map