import { __assign, __awaiter, __generator, __read, __spread, __values } from "tslib";
import { IGXE } from "@intelligentgraphics/igd.core";
import { Cancellation } from "@intelligentgraphics/ig.utilities";
export var executeConfigureArticlesOperation = function (comIds, changes, articleQuery, scheduler, productDataManager) { return __awaiter(void 0, void 0, void 0, function () {
    var results, roots, processArticle, processChildren;
    return __generator(this, function (_a) {
        switch (_a.label) {
            case 0:
                results = [];
                roots = findArticleRoots(comIds, articleQuery);
                processArticle = function (comId, context) { return __awaiter(void 0, void 0, void 0, function () {
                    var article, _a, _b;
                    return __generator(this, function (_c) {
                        switch (_c.label) {
                            case 0:
                                article = articleQuery.getArticleByComId(comId);
                                if (article.categories.onlyConfigurableThroughParent) {
                                    if (context.parentConfigured) {
                                        results.push({
                                            type: "configure",
                                            comId: comId,
                                        });
                                    }
                                    return [2 /*return*/, processChildren(article, productDataManager, context)];
                                }
                                // if (article.categories.inheritParentConfiguration) {
                                // }
                                _b = (_a = results).push;
                                return [4 /*yield*/, scheduler
                                        .queueConfigureOperation(article.comId, IGXE.normalizePropertyValueChanges(changes), function (changes) {
                                        return configureArticle(article, changes, productDataManager);
                                    })
                                        .catch(function (error) {
                                        return Cancellation.isCancelError(error)
                                            ? Promise.resolve(undefined)
                                            : Promise.reject(error);
                                    })];
                            case 1:
                                // if (article.categories.inheritParentConfiguration) {
                                // }
                                _b.apply(_a, [_c.sent()]);
                                return [2 /*return*/, processChildren(article, productDataManager, __assign(__assign({}, context), { parentConfigured: true }))];
                        }
                    });
                }); };
                processChildren = function (article, productDataManager, branchContext) { return __awaiter(void 0, void 0, void 0, function () {
                    var aliveChildren, currentChildren, allChildComIds;
                    return __generator(this, function (_a) {
                        switch (_a.label) {
                            case 0: return [4 /*yield*/, productDataManager.getSubArticleIDs(article.comId)];
                            case 1:
                                aliveChildren = _a.sent();
                                currentChildren = article.children;
                                allChildComIds = Array.from(new Set(__spread(aliveChildren, currentChildren)));
                                return [4 /*yield*/, Promise.all(allChildComIds.map(function (comId) {
                                        var created = currentChildren.indexOf(comId) === -1;
                                        if (created) {
                                            results.push({
                                                type: "create",
                                                comId: comId,
                                                parent: article.comId,
                                            });
                                            return;
                                        }
                                        var deleted = aliveChildren.indexOf(comId) === -1;
                                        if (deleted) {
                                            results.push({
                                                type: "delete",
                                                comId: comId,
                                            });
                                            return;
                                        }
                                        return processArticle(comId, branchContext);
                                    }))];
                            case 2:
                                _a.sent();
                                return [2 /*return*/];
                        }
                    });
                }); };
                return [4 /*yield*/, Promise.all(roots.map(function (comId) { return processArticle(comId, {}); }))];
            case 1:
                _a.sent();
                return [2 /*return*/, results.filter(Boolean)];
        }
    });
}); };
var configureArticle = function (article, changes, productDataManager) { return __awaiter(void 0, void 0, void 0, function () {
    var optimizedChanges;
    return __generator(this, function (_a) {
        switch (_a.label) {
            case 0:
                optimizedChanges = getPotentialChanges(article.configuration, changes);
                if (optimizedChanges === false) {
                    return [2 /*return*/];
                }
                return [4 /*yield*/, productDataManager.setPropValues(article.comId, optimizedChanges)];
            case 1:
                _a.sent();
                return [2 /*return*/, {
                        type: "configure",
                        comId: article.comId,
                    }];
        }
    });
}); };
var findArticleRoots = function (comIds, articleQuery) {
    var e_1, _a;
    var result = new Set();
    try {
        for (var comIds_1 = __values(comIds), comIds_1_1 = comIds_1.next(); !comIds_1_1.done; comIds_1_1 = comIds_1.next()) {
            var comId = comIds_1_1.value;
            var article = articleQuery.getArticleByComId(comId);
            if (article === undefined) {
                continue;
            }
            if (article.parent === undefined) {
                result.add(comId);
                continue;
            }
            var parent_1 = articleQuery.getFirstArticleParent(comId, function (article) { return article.parent === undefined; });
            result.add(parent_1.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 Array.from(result);
};
/**
 * Determines changes between two article configurations/property change objects
 *
 * Returns false when both are equal.
 * Omits all values which are equal between both objects.
 *
 * @param {IGXE.ArticleConfigurationValues} currentConfiguration
 * @param {IGXE.PropertyValueChanges} changes
 * @returns
 */
var getPotentialChanges = function (currentConfiguration, changes) {
    var e_2, _a, e_3, _b;
    var optimizedChanges = new Map();
    var normalizedChanges = IGXE.normalizePropertyValueChanges(changes);
    try {
        for (var normalizedChanges_1 = __values(normalizedChanges), normalizedChanges_1_1 = normalizedChanges_1.next(); !normalizedChanges_1_1.done; normalizedChanges_1_1 = normalizedChanges_1.next()) {
            var _c = normalizedChanges_1_1.value, key = _c.key, value = _c.value;
            if (currentConfiguration[key] !== value) {
                optimizedChanges.set(key, value);
            }
        }
    }
    catch (e_2_1) { e_2 = { error: e_2_1 }; }
    finally {
        try {
            if (normalizedChanges_1_1 && !normalizedChanges_1_1.done && (_a = normalizedChanges_1.return)) _a.call(normalizedChanges_1);
        }
        finally { if (e_2) throw e_2.error; }
    }
    if (optimizedChanges.size === 0) {
        return false;
    }
    var resultChanges = [];
    try {
        for (var optimizedChanges_1 = __values(optimizedChanges), optimizedChanges_1_1 = optimizedChanges_1.next(); !optimizedChanges_1_1.done; optimizedChanges_1_1 = optimizedChanges_1.next()) {
            var _d = __read(optimizedChanges_1_1.value, 2), key = _d[0], value = _d[1];
            resultChanges.push({
                key: key,
                value: value,
            });
        }
    }
    catch (e_3_1) { e_3 = { error: e_3_1 }; }
    finally {
        try {
            if (optimizedChanges_1_1 && !optimizedChanges_1_1.done && (_b = optimizedChanges_1.return)) _b.call(optimizedChanges_1);
        }
        finally { if (e_3) throw e_3.error; }
    }
    return resultChanges;
};
