import { Hierarchy } from "@intelligentgraphics/ig.gfx.core";
import { isValue } from "@intelligentgraphics/ig.utilities";
import { IGXE } from "@intelligentgraphics/igd.core";
export const createArticleQuery = (articleState) => {
    const getPropertyOfArticle = (comId, property) => {
        const article = articleState.getArticleByComId(comId);
        if (article === undefined) {
            throw new Error(`Can not access property "${property}" of unknown article "${comId}"`);
        }
        return article[property];
    };
    const createPropertyExtractor = (property) => (comId) => getPropertyOfArticle(comId, property);
    const getAllArticles = () => articleState
        .getAllComIds()
        .map(comId => articleState.getArticleByComId(comId));
    const getFilteredArticles = (filter) => getAllArticles().filter(filter);
    const getArticlesOfSource = (sourceId) => getFilteredArticles(({ source }) => source === sourceId);
    const getArticlesWithCategory = (category) => getFilteredArticles(({ categories }) => categories[category]);
    const getArticlesOfType = (type) => getFilteredArticles(article => article.type === type);
    const getGraphicalArticles = () => getArticlesOfType("graphical");
    const getFirstArticle = (where = () => true) => getAllArticles().find(where);
    const getFirstArticleParent = (comId, where = () => true) => {
        let article = articleState.getArticleByComId(comId);
        if (article === undefined) {
            throw new Error(`Can not query parents of unknown article "${comId}"`);
        }
        while (article.parent !== undefined) {
            article = articleState.getArticleByComId(article.parent);
            if (article === undefined) {
                throw new Error(`Parent of article "${comId}" no longer exists`);
            }
            if (where(article)) {
                return article;
            }
        }
        return undefined;
    };
    const getDeepArticleChildren = (comId) => {
        const result = [];
        const collect = (comId) => {
            const article = articleState.getArticleByComId(comId);
            result.push(comId);
            article.children.forEach(collect);
        };
        const children = getPropertyOfArticle(comId, "children");
        children.forEach(collect);
        return result;
    };
    const getArticleProperty = (comId, propertyKey) => {
        const properties = getPropertyOfArticle(comId, "properties");
        return IGXE.findProperty(properties, propertyKey);
    };
    const getHeadItem = (sourceId) => getAllArticles().find(article => article.type === "headItem" && article.source === sourceId);
    const getArticlesByComIds = (comIds) => comIds
        .map(comId => articleState.getArticleByComId(comId))
        .filter(isValue);
    const getArticleByGfxId = (gfxId) => {
        const article = articleState.getArticleByGfxId(gfxId);
        if (article !== undefined) {
            return article;
        }
        const rootId = Hierarchy.fixIfSuperRoot(gfxId);
        return articleState.getArticleByGfxId(rootId);
    };
    const getArticleGfxSuperRootId = (comId) => {
        const gfxId = getPropertyOfArticle(comId, "gfxId");
        if (gfxId === undefined) {
            return undefined;
        }
        return Hierarchy.getSuperRootGfxId(gfxId) || undefined;
    };
    const getAllGfxIds = () => getFilteredArticles(article => article.type === "graphical" && article.gfxId !== undefined).map(article => article.gfxId);
    return {
        getHeadItem,
        getAllComIds: articleState.getAllComIds,
        getAllArticles,
        getFilteredArticles,
        getArticlesOfSource,
        getArticlesWithCategory,
        getArticlesOfType,
        getArticlesByComIds,
        getGraphicalArticles,
        getAllGfxIds,
        getComIdByGfxId: articleState.getComIdByGfxId,
        getArticleByComId: articleState.getArticleByComId,
        getArticleId: createPropertyExtractor("articleId"),
        getArticleGfxId: createPropertyExtractor("gfxId"),
        getArticleGfxSuperRootId,
        getArticleConfiguration: createPropertyExtractor("configuration"),
        getArticleProperties: createPropertyExtractor("properties"),
        getArticleProperty,
        getArticleCategories: createPropertyExtractor("categories"),
        getArticleData: createPropertyExtractor("data"),
        getArticleSourceData: createPropertyExtractor("sourceData"),
        getArticleSource: createPropertyExtractor("source"),
        getArticleParent: createPropertyExtractor("parent"),
        getArticleChildren: createPropertyExtractor("children"),
        getArticlePlacement: createPropertyExtractor("placement"),
        getArticleInfo: createPropertyExtractor("info"),
        getFirstArticle,
        getFirstArticleParent,
        getDeepArticleChildren,
        getArticleByGfxId,
    };
};
