"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var ig_utilities_1 = require("@intelligentgraphics/ig.utilities");
var Utilities_1 = require("./Utilities");
var Logger_1 = require("./Logger");
var Logger = Logger_1.default.createSubLogger("ArticleManager");
exports.createArticleManager = function (serviceManager, articleState, articleQuery, operationResultHandler, applicationState) {
    var createArticleFromCatalogItem = function (_a) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
        var backend, articleNumber, params, initialConfiguration, results;
        var catalogItem = _a.catalogItem, source = _a.source, additionalInfo = _a.additionalInfo, passThrough = tslib_1.__rest(_a, ["catalogItem", "source", "additionalInfo"]);
        return tslib_1.__generator(this, function (_b) {
            switch (_b.label) {
                case 0: return [4 /*yield*/, serviceManager.getSourceBackend(source)];
                case 1:
                    backend = _b.sent();
                    if (backend === undefined) {
                        throw new Error("No backend has been registered for \"" + source + "\", no article number can be created.");
                    }
                    articleNumber = backend.createArticleNumber(catalogItem);
                    params = tslib_1.__assign(tslib_1.__assign({}, passThrough), { source: source, articleNumber: tslib_1.__assign(tslib_1.__assign({}, articleNumber), additionalInfo) });
                    initialConfiguration = Utilities_1.ConfigResolver.resolveInitialConfiguration(params, articleQuery, applicationState.getValue("selection"));
                    return [4 /*yield*/, serviceManager
                            .getOperatorForSourceId(source)
                            .addArticle(tslib_1.__assign(tslib_1.__assign({}, params), { initialConfiguration: initialConfiguration }))];
                case 2:
                    results = _b.sent();
                    return [4 /*yield*/, operationResultHandler.processOperationResults(results)];
                case 3:
                    _b.sent();
                    return [2 /*return*/, results[0].comId];
            }
        });
    }); };
    var createArticleFromArticleNumber = function (params) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
        var creationResults;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, serviceManager
                        .getOperatorForSourceId(params.source)
                        .addArticle(tslib_1.__assign(tslib_1.__assign({}, params), { initialConfiguration: Utilities_1.ConfigResolver.resolveInitialConfiguration(params, articleQuery, applicationState.getValue("selection")) }))];
                case 1:
                    creationResults = _a.sent();
                    return [4 /*yield*/, operationResultHandler.processOperationResults(creationResults)];
                case 2:
                    _a.sent();
                    return [2 /*return*/, creationResults[0].comId];
            }
        });
    }); };
    var changeArticleProperty = function (comId, propertyKey, newValue) {
        var _a;
        return changeProperties([comId], (_a = {}, _a[propertyKey] = newValue, _a));
    };
    var changeArticleProperties = function (comId, changes) { return changeProperties([comId], changes); };
    var changeProperty = function (comIds, propertyKey, newValue) {
        var _a;
        return changeProperties(comIds, (_a = {}, _a[propertyKey] = newValue, _a));
    };
    var changeProperties = function (comIds, changes) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
        var comIdsBySources, results;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    comIdsBySources = groupArticlesBySource(comIds);
                    results = [];
                    return [4 /*yield*/, Promise.all(Array.from(comIdsBySources).map(function (_a) {
                            var _b = tslib_1.__read(_a, 2), sourceId = _b[0], comIds = _b[1];
                            return serviceManager
                                .getOperatorForSourceId(sourceId)
                                .configureArticles(comIds, changes)
                                .then(function (sourceResults) { return results.push.apply(results, tslib_1.__spread(sourceResults)); });
                        }))];
                case 1:
                    _a.sent();
                    return [4 /*yield*/, operationResultHandler.processOperationResults(results)];
                case 2:
                    _a.sent();
                    return [2 /*return*/];
            }
        });
    }); };
    var cloneArticle = function (params) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
        var article, cloneResults;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    article = articleQuery.getArticleByComId(params.comId);
                    if (article === undefined) {
                        throw new Error("Can not clone unknown article \"" + params.comId + "\"");
                    }
                    return [4 /*yield*/, serviceManager
                            .getOperatorForComId(params.comId)
                            .cloneArticle(params)];
                case 1:
                    cloneResults = _a.sent();
                    return [4 /*yield*/, operationResultHandler.processOperationResults(cloneResults)];
                case 2:
                    _a.sent();
                    return [2 /*return*/, cloneResults[0].comId];
            }
        });
    }); };
    var deleteArticle = function (comId) { return deleteArticles([comId]); };
    var deleteArticles = function (comIds) { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
        var deleteTargets, comIds_1, comIds_1_1, comId, article, deleteResults, flattenedResults, deleteResults_1, deleteResults_1_1, results;
        var e_1, _a, e_2, _b;
        return tslib_1.__generator(this, function (_c) {
            switch (_c.label) {
                case 0:
                    deleteTargets = [];
                    try {
                        for (comIds_1 = tslib_1.__values(comIds), comIds_1_1 = comIds_1.next(); !comIds_1_1.done; comIds_1_1 = comIds_1.next()) {
                            comId = comIds_1_1.value;
                            article = articleQuery.getArticleByComId(comId);
                            if (article === undefined) {
                                Logger.warn("Article with comId \"" + comId + "\" does not exist. Skipping deletion");
                                continue;
                            }
                            deleteTargets.push(comId);
                        }
                    }
                    catch (e_1_1) { e_1 = { error: e_1_1 }; }
                    finally {
                        try {
                            if (comIds_1_1 && !comIds_1_1.done && (_a = comIds_1.return)) _a.call(comIds_1);
                        }
                        finally { if (e_1) throw e_1.error; }
                    }
                    return [4 /*yield*/, Promise.all(deleteTargets.map(function (comId) {
                            return serviceManager.getOperatorForComId(comId).deleteArticle(comId);
                        }))];
                case 1:
                    deleteResults = _c.sent();
                    flattenedResults = [];
                    try {
                        for (deleteResults_1 = tslib_1.__values(deleteResults), deleteResults_1_1 = deleteResults_1.next(); !deleteResults_1_1.done; deleteResults_1_1 = deleteResults_1.next()) {
                            results = deleteResults_1_1.value;
                            flattenedResults.push.apply(flattenedResults, tslib_1.__spread(results));
                        }
                    }
                    catch (e_2_1) { e_2 = { error: e_2_1 }; }
                    finally {
                        try {
                            if (deleteResults_1_1 && !deleteResults_1_1.done && (_b = deleteResults_1.return)) _b.call(deleteResults_1);
                        }
                        finally { if (e_2) throw e_2.error; }
                    }
                    return [4 /*yield*/, operationResultHandler.processOperationResults(flattenedResults)];
                case 2:
                    _c.sent();
                    return [2 /*return*/];
            }
        });
    }); };
    var createArticlePropertySetter = function (property) { return function (comId, value) {
        return articleState.updateArticleProperty(comId, property, value);
    }; };
    var setArticlePlacement = function (comId, placement) {
        var currentPlacement = articleQuery.getArticlePlacement(comId);
        if ((currentPlacement === undefined) === (placement === undefined) &&
            placement !== undefined &&
            ig_utilities_1.Obj.shallowEqual(placement.position, currentPlacement.position) &&
            ig_utilities_1.Obj.shallowEqual(placement.rotation, currentPlacement.rotation)) {
            return;
        }
        articleState.updateArticleProperty(comId, "placement", placement);
    };
    var groupArticlesBySource = function (comIds) {
        var e_3, _a;
        var comIdsBySources = new Map();
        try {
            for (var comIds_2 = tslib_1.__values(comIds), comIds_2_1 = comIds_2.next(); !comIds_2_1.done; comIds_2_1 = comIds_2.next()) {
                var comId = comIds_2_1.value;
                var sourceId = articleQuery.getArticleSource(comId);
                var sourceGroup = comIdsBySources.get(sourceId);
                if (sourceGroup === undefined) {
                    sourceGroup = [];
                    comIdsBySources.set(sourceId, sourceGroup);
                }
                sourceGroup.push(comId);
            }
        }
        catch (e_3_1) { e_3 = { error: e_3_1 }; }
        finally {
            try {
                if (comIds_2_1 && !comIds_2_1.done && (_a = comIds_2.return)) _a.call(comIds_2);
            }
            finally { if (e_3) throw e_3.error; }
        }
        return comIdsBySources;
    };
    var getGfxRepresentation = function (comId, options) {
        Utilities_1.ArticleUtil.getArticleOrThrow(articleQuery, comId);
        var operator = serviceManager.getOperatorForComId(comId);
        return operator.getGfxRepresentation(comId, options);
    };
    return {
        changeProperties: changeProperties,
        changeProperty: changeProperty,
        createArticleFromArticleNumber: createArticleFromArticleNumber,
        createArticleFromCatalogItem: createArticleFromCatalogItem,
        changeArticleProperties: changeArticleProperties,
        changeArticleProperty: changeArticleProperty,
        deleteArticle: deleteArticle,
        deleteArticles: deleteArticles,
        cloneArticle: cloneArticle,
        setArticleData: createArticlePropertySetter("data"),
        setArticleGfxId: createArticlePropertySetter("gfxId"),
        setArticlePlacement: setArticlePlacement,
        getGfxRepresentation: getGfxRepresentation,
    };
};
