import * as React from "react";
import { IGXE } from "@intelligentgraphics/igd.core";
import { createBasket, } from "@intelligentgraphics/igd.productdata";
import { useSessionContext } from "../SessionContext";
import { convert, getDefaultUnitString, getGroupOfUnit } from "../Units";
import { EBomComponentEntryType, } from "./Types";
const buildState = (session, basket, { flatten = false, useVarText = false, units }) => {
    const response = [];
    const buildLevel = (articles, parentUID) => {
        const levelItems = [];
        for (const item of articles) {
            if (item.data.hidden) {
                continue;
            }
            // if (item.ItemType === IGXB.EItemType.Group) {
            // 	if (item.Items.every(subItem => subItem.Hidden === true)) {
            // 		continue;
            // 	}
            // 	const groupEntry: IBomComponentGroupEntry = {
            // 		Caption: item.Caption || [],
            // 		ItemType: EBomComponentEntryType.Group,
            // 		UID: item.UID,
            // 		Items: []
            // 	};
            // 	if (flatten) {
            // 		response.push(groupEntry);
            // 	}
            // 	if (item.Items) {
            // 		const result = buildLevel(item.Items, item.UID);
            // 		if (result.length === 0) {
            // 			continue;
            // 		}
            // 		if (!flatten) {
            // 			groupEntry.Items = result;
            // 		}
            // 	}
            // 	levelItems.push(groupEntry);
            // 	continue;
            // }
            if (item.type === "set") {
                const setEntry = {
                    Caption: item.info.shortText || [],
                    ItemType: EBomComponentEntryType.Set,
                    UID: item.comId,
                    Items: [],
                    SetId: item.articleId,
                    InstanceId: item.comId,
                    Position: basket.getPositionString(item.comId),
                    Price: basket.getSinglePriceText(item.comId) || "",
                    ShortText: item.info.shortText,
                    LongText: item.info.longText,
                    VarText: getVarText(item.info.varText),
                    Name: item.info.name,
                };
                if (flatten) {
                    response.push(setEntry);
                }
                if (item.children) {
                    const result = buildLevel(session.getArticlesByComIds(item.children), item.comId);
                    if (!flatten) {
                        setEntry.Items = result;
                    }
                }
                levelItems.push(setEntry);
            }
            if (item.type === "commercial" || item.type === "graphical") {
                const properties = getArticleProperties(session, item.comId, useVarText, units);
                const articleEntry = {
                    UID: item.comId,
                    ItemType: EBomComponentEntryType.Article,
                    Position: basket.getPositionString(item.comId),
                    ArticleId: item.articleId,
                    Image: item.info.image,
                    InstanceId: item.comId,
                    ShortText: item.info.shortText,
                    LongText: item.info.longText,
                    VarText: getVarText(item.info.varText),
                    Quantity: "1",
                    SinglePrice: basket.getSinglePriceText(item.comId) || "",
                    TotalPrice: basket.getSinglePriceText(item.comId) || "",
                    Properties: properties,
                    Name: item.info.name,
                };
                if (flatten) {
                    response.push(articleEntry);
                }
                if (item.children) {
                    const result = buildLevel(session.getArticlesByComIds(item.children), item.comId);
                    if (!flatten) {
                        articleEntry.SubItems = result;
                    }
                }
                levelItems.push(articleEntry);
                continue;
            }
            // if (item.ItemType === IGXB.EItemType.Text) {
            // 	if (!Array.isArray(item.Text)) {
            // 		item.Text = [item.Text];
            // 	}
            // 	const textEntry: IBomComponentTextEntry = {
            // 		Text: item.Text,
            // 		UID: item.UID,
            // 		ItemType: EBomComponentEntryType.Text
            // 	};
            // 	if (flatten) {
            // 		response.push(textEntry);
            // 	}
            // 	levelItems.push(textEntry);
            // }
        }
        return levelItems;
    };
    const deepResult = buildLevel(session.getFilteredArticles(article => article.parent === undefined), undefined);
    const items = flatten ? response : deepResult;
    const totals = basket.getBomTotals();
    const totalEntry = totals.find(entry => entry.type === "total");
    if (!totalEntry) {
        throw new Error(`Total calculation requires one entry with a type of "total" to be returned by the basket.`);
    }
    return {
        items,
        total: totalEntry.text,
    };
};
const getVarText = (textEntries) => {
    if (!textEntries) {
        return [];
    }
    return textEntries.map(({ key, value }) => `${key}: ${value}`);
};
const getArticleProperties = (session, comId, useVarText, units) => {
    const article = session.getArticleByComId(comId);
    if (article === undefined) {
        throw new Error(`Can not read properties and configuration of unknown article: ${comId}`);
    }
    if (useVarText) {
        return article.info.varText.map(entry => ({
            property: entry.key,
            value: entry.value,
        }));
    }
    const { properties, configuration } = article;
    const visibleConfiguredProperties = properties.filter(prop => prop.Visible && configuration[prop.Key]);
    return IGXE.createActiveSubPropertyInjectedPropertyList(visibleConfiguredProperties).map(prop => {
        let text = "";
        if (prop.ValueType === IGXE.EPropertyType.Int ||
            prop.ValueType === IGXE.EPropertyType.Float) {
            const tUnitGroup = getGroupOfUnit(prop.ValueUnit);
            text = prop.Value ? prop.Value.toString() : "";
            if (units) {
                const newUnit = units[tUnitGroup];
                text =
                    convert(prop.Value, prop.ValueUnit, newUnit).toString() +
                        " " +
                        getDefaultUnitString(newUnit);
            }
        }
        else if (prop.Value !== undefined) {
            const valueDefinition = IGXE.findValueDefinition(prop, prop.Value);
            if (valueDefinition !== undefined && valueDefinition.Text) {
                text = valueDefinition.Text.join(" ");
            }
        }
        let propText = prop.Text.join(" ");
        propText =
            propText.indexOf(":") === -1 ? propText : propText.slice(0, -1);
        return {
            property: propText,
            value: text,
        };
    });
};
const BasketComponent = props => {
    const { session, basket } = useSessionContext();
    const providedBasket = props.basket || basket;
    //TODO: update on settings change
    const settingsRef = React.useRef(undefined);
    settingsRef.current = {
        flatten: props.flatten,
        locale: props.locale || session.getLanguage(),
        units: props.units,
        useVarText: props.useVarText,
    };
    const [state, setState] = React.useState({
        items: [],
        total: "",
    });
    React.useEffect(() => {
        let batchTimer;
        const basket = providedBasket !== undefined
            ? providedBasket
            : createBasket(session);
        const update = () => {
            if (batchTimer !== undefined) {
                return;
            }
            batchTimer = setTimeout(() => {
                setState(buildState(session, basket, settingsRef.current));
                batchTimer = undefined;
            });
        };
        const subscription = session.subscribe({
            ItemCreated: update,
            ItemConfigured: update,
            ItemRemoved: update,
        });
        update();
        return () => {
            if (providedBasket === undefined) {
                basket.destroy();
            }
            subscription.destroy();
            clearTimeout(batchTimer);
        };
    }, [session, providedBasket]);
    return props.children(state);
};
BasketComponent.displayName = "BasketComponent";
export default BasketComponent;
