"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.RestImporter = void 0;
const validation_1 = require("../validation");
const utils_1 = require("../../../../db/utils");
const openapi2_1 = require("./sources/openapi2");
const openapi3_1 = require("./sources/openapi3");
const curl_1 = require("./sources/curl");
// @ts-ignore
const context_1 = require("@devlego/backend-core/context");
const backend_core_1 = require("@devlego/backend-core");
class RestImporter {
    constructor(data) {
        this.init = () => __awaiter(this, void 0, void 0, function* () {
            for (let source of this.sources) {
                if (yield source.isSupported(this.data)) {
                    this.source = source;
                    break;
                }
            }
        });
        this.getInfo = () => __awaiter(this, void 0, void 0, function* () {
            return this.source.getInfo();
        });
        this.importQueries = (datasourceId) => __awaiter(this, void 0, void 0, function* () {
            // construct the queries
            let queries = yield this.source.getQueries(datasourceId);
            // validate queries
            const errorQueries = [];
            const schema = (0, validation_1.queryValidation)();
            queries = queries
                .filter(query => {
                const validation = schema.validate(query);
                if (validation.error) {
                    errorQueries.push(query);
                    return false;
                }
                return true;
            })
                .map(query => {
                query._id = (0, utils_1.generateQueryID)(query.datasourceId);
                return query;
            });
            // persist queries
            const db = (0, context_1.getAppDB)();
            const response = yield db.bulkDocs(queries);
            // create index to seperate queries and errors
            const queryIndex = queries.reduce((acc, query) => {
                if (query._id) {
                    acc[query._id] = query;
                }
                return acc;
            }, {});
            // check for failed writes
            response.forEach((query) => {
                if (!query.ok) {
                    errorQueries.push(queryIndex[query.id]);
                    delete queryIndex[query.id];
                }
            });
            const successQueries = Object.values(queryIndex);
            // events
            const count = successQueries.length;
            const importSource = this.source.getImportSource();
            const datasource = yield db.get(datasourceId);
            yield backend_core_1.events.query.imported(datasource, importSource, count);
            for (let query of successQueries) {
                yield backend_core_1.events.query.created(datasource, query);
            }
            return {
                errorQueries,
                queries: successQueries,
            };
        });
        this.data = data;
        this.sources = [new openapi2_1.OpenAPI2(), new openapi3_1.OpenAPI3(), new curl_1.Curl()];
    }
}
exports.RestImporter = RestImporter;
