import { generateId } from "@intelligentgraphics/ig.utilities";
import { IGXB, IGXE } from "@intelligentgraphics/igd.core";
export const createIGXB = (articleQuery, { autoGrouping = true, priceType = IGXB.EPriceType.Gross, vat = 0, projectData = {
    Id: generateId(),
    Title: "A new Project",
    Creation: new Date().toUTCString(),
}, customData = {}, basket, } = {}) => {
    const result = {
        FormatVersion: `${IGXB.CurrentMajorVersion}.${IGXB.CurrentMinorVersion}`,
        VAT: vat,
        PriceType: priceType,
        CustomData: customData,
        ProjectData: projectData,
        Items: [],
    };
    const roots = articleQuery.getFilteredArticles(article => article.parent === undefined);
    for (const article of roots) {
        let parentItems;
        if (!autoGrouping) {
            parentItems = result.Items;
        }
        else {
            parentItems = findOrCreateSourceGroup(article, result.Items);
        }
        buildItemTree(articleQuery, article, parentItems, basket);
    }
    return result;
};
const findOrCreateSourceGroup = (article, existingRootItems) => {
    const parent = existingRootItems.find(item => item.ItemType === IGXB.EItemType.Group &&
        item.Identifier === article.source);
    if (parent !== undefined) {
        return parent.Items;
    }
    const { manufacturerName, programName } = article.info;
    const newParent = {
        ItemType: IGXB.EItemType.Group,
        Items: [],
        UID: generateId(),
        Caption: manufacturerName + " " + programName,
        Identifier: article.source,
    };
    existingRootItems.push(newParent);
    return newParent.Items;
};
const buildItemTree = async (articleQuery, article, parentItems, basket) => {
    const item = createIGXBItem(article, basket);
    parentItems.push(item);
    if (article.children.length > 0) {
        const children = article.children.map(comId => articleQuery.getArticleByComId(comId));
        let childArray;
        if (item.ItemType === IGXB.EItemType.Group ||
            item.ItemType === IGXB.EItemType.Set) {
            childArray = item.Items;
        }
        else if (item.ItemType === IGXB.EItemType.Article) {
            childArray = item.SubItems;
        }
        if (childArray === undefined) {
            throw new Error(`Article "${article.comId}" has children, but they can not be reflected in the igxb since the igxb representation of the article doesn't allow children`);
        }
        await Promise.all(children.map(article => buildItemTree(articleQuery, article, childArray, basket)));
    }
};
const createCommercialArticle = (article, priceFormatter) => {
    const normalArticle = createArticle(article, priceFormatter);
    normalArticle.Data.dontRestore = true;
    normalArticle.IsCommercial = true;
    return normalArticle;
};
const createArticle = (article, priceFormatter) => {
    const { manufacturerName, manufacturerId, prices, programName, programId, shortText, longText, image, name, } = article.info;
    const item = {
        ItemType: IGXB.EItemType.Article,
        ComId: article.comId,
        Configuration: article.configuration,
        Source: article.source,
        ManufacturerId: manufacturerId,
        ManufacturerName: manufacturerName,
        ProgramId: programId,
        ProgramName: programName,
        ArticleShortText: shortText,
        ArticleLongText: longText,
        Data: { ...article.data },
        SubItems: [],
        Image: image,
        ArticleId: article.articleId,
        ArticlePackageId: article.articleNumber !== undefined
            ? article.articleNumber.articlePackageId
            : undefined,
        IsCommercial: false,
        UID: generateId(),
        Categories: { ...article.categories },
        Hidden: article.data.hidden,
        ArticleName: name,
        ArticleNumber: article.articleNumber,
    };
    if (article.placement !== undefined) {
        item.Position = article.placement.position;
        item.Rotation = article.placement.rotation;
    }
    addPrices(item, prices, priceFormatter);
    return item;
};
const createImpression = (article, basket) => {
    const { ItemType, SubItems, Position, Rotation, ...baseItem } = createArticle(article, basket);
    return {
        ItemType: IGXB.EItemType.Impression,
        ...baseItem,
    };
};
const createSet = (article, basket) => {
    const { prices } = article.info;
    const item = {
        ItemType: IGXB.EItemType.Set,
        ComId: article.comId,
        Items: [],
        Source: article.source,
        Configuration: article.configuration,
        SetId: article.articleId,
        UID: generateId(),
        Categories: article.categories,
        Hidden: article.data.hidden,
    };
    addPrices(item, prices, basket);
    return item;
};
const itemBuilders = {
    commercial: createCommercialArticle,
    graphical: createArticle,
    impression: createImpression,
    set: createSet,
    headItem: createCommercialArticle,
};
const createIGXBItem = (article, basket) => {
    const builder = itemBuilders[article.type];
    return builder(article, basket);
};
const addPrices = (item, prices, basket) => {
    for (const price of prices) {
        if (price.Level === IGXE.EPriceLevel.Base) {
            //TODO: price range for this
            item.SinglePrice = price.Value;
            item.Currency = price.Currency;
            break;
        }
        if (item.ItemType !== IGXB.EItemType.Article) {
            continue;
        }
        if (item.AdditionalPrices === undefined) {
            item.AdditionalPrices = [];
        }
        const tNewAddPrice = {
            Text: price.Text || "",
            Currency: price.Currency,
            Level: price.Level === IGXE.EPriceLevel.AddToBase
                ? IGXB.EAddPriceRule.ToBase
                : IGXB.EAddPriceRule.ToSum,
            Value: price.Value,
            RangeMin: price.RangeMin,
            RangeMax: price.RangeMax,
        };
        item.AdditionalPrices.push(tNewAddPrice);
    }
    if (basket !== undefined) {
        item.SinglePriceText = basket.getSinglePriceText(item.ComId);
    }
};
