import API from "../../Utils/API/API";
import ModelAPI from "../../Utils/ModelAPI/ModelAPI";
import ComponentLoader from "../ComponentLoader/ComponentLoader";
import ErrorMessage from "../ErrorMessage/ErrorMessage";
import Input from "../Input/Input";
import StaticModelList from "../ModelList/StaticModelList";
import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
import BadDataException from "../../../Types/Exception/BadDataException";
import ObjectID from "../../../Types/ObjectID";
import React, { useEffect, useState } from "react";
const ModelList = (props) => {
    const [selectedList, setSelectedList] = useState([]);
    const [modelList, setModalList] = useState([]);
    const [error, setError] = useState("");
    const [isLoading, setIsLoading] = useState(false);
    const [searchedList, setSearchedList] = useState([]);
    const [searchText, setSearchText] = useState("");
    useEffect(() => {
        var _a;
        (_a = props.onSelectChange) === null || _a === void 0 ? void 0 : _a.call(props, selectedList);
    }, [selectedList]);
    useEffect(() => {
        fetchItems().catch((err) => {
            setError(API.getFriendlyMessage(err));
        });
    }, [props.refreshToggle]);
    useEffect(() => {
        fetchItems().catch((err) => {
            setError(API.getFriendlyMessage(err));
        });
    }, []);
    useEffect(() => {
        if (!props.isSearchEnabled) {
            setSearchedList([...modelList]);
        }
    }, [props.isSearchEnabled, modelList]);
    const fetchItems = async () => {
        var _a;
        setError("");
        setIsLoading(true);
        try {
            const select = Object.assign({}, props.select);
            if (props.dragDropIdField &&
                !Object.keys(select).includes(props.dragDropIdField)) {
                select[props.dragDropIdField] = true;
            }
            if (props.dragDropIndexField &&
                !Object.keys(select).includes(props.dragDropIndexField)) {
                select[props.dragDropIndexField] = true;
            }
            let listResult = {
                data: [],
                count: 0,
                skip: 0,
                limit: 0,
            };
            if (props.overrideFetchApiUrl) {
                const result = (await API.post({
                    url: props.overrideFetchApiUrl,
                    data: {},
                    headers: {},
                }));
                listResult = {
                    data: BaseModel.fromJSONArray(result.data, props.modelType),
                    count: result.data.length,
                    skip: 0,
                    limit: LIMIT_PER_PROJECT,
                };
            }
            else {
                listResult = await ModelAPI.getList({
                    modelType: props.modelType,
                    query: Object.assign({}, props.query),
                    limit: LIMIT_PER_PROJECT,
                    skip: 0,
                    select: select,
                    sort: props.sortBy
                        ? {
                            [props.sortBy]: props.sortOrder,
                        }
                        : {},
                    requestOptions: props.fetchRequestOptions,
                });
            }
            (_a = props.onListLoaded) === null || _a === void 0 ? void 0 : _a.call(props, listResult.data);
            setModalList(listResult.data);
        }
        catch (err) {
            setError(API.getFriendlyMessage(err));
        }
        setIsLoading(false);
    };
    useEffect(() => {
        if (!searchText) {
            setSearchedList([...modelList]);
        }
        else {
            // search
            setSearchedList([...modelList].filter((model) => {
                const includedInSearch = model.getValue(props.titleField)
                    .toLowerCase()
                    .includes(searchText);
                if (!includedInSearch && props.descriptionField) {
                    return model.getValue(props.descriptionField)
                        .toLowerCase()
                        .includes(searchText);
                }
                return includedInSearch;
            }));
        }
    }, [modelList, searchText]);
    const deleteItem = async (item) => {
        if (!item.id) {
            throw new BadDataException("item.id cannot be null");
        }
        setIsLoading(true);
        try {
            await ModelAPI.deleteItem({
                modelType: props.modelType,
                id: item.id,
            });
            await fetchItems();
        }
        catch (err) {
            setError(API.getFriendlyMessage(err));
        }
        setIsLoading(false);
    };
    return (React.createElement("div", null,
        React.createElement("div", null, !isLoading && !error && props.isSearchEnabled && (React.createElement("div", { className: "p-2" },
            React.createElement(Input, { placeholder: "Search...", onChange: (value) => {
                    setSearchText(value);
                } })))),
        React.createElement("div", { className: "max-h-96 mb-5 overflow-y-auto p-2" },
            error ? React.createElement(ErrorMessage, { message: error }) : React.createElement(React.Fragment, null),
            isLoading ? React.createElement(ComponentLoader, null) : React.createElement(React.Fragment, null),
            !isLoading && !error && searchedList.length === 0 ? (React.createElement(ErrorMessage, { message: searchText
                    ? "No items match your search"
                    : props.noItemsMessage || "No items found." })) : (React.createElement(React.Fragment, null)),
            !error && !isLoading && (React.createElement(StaticModelList, { enableDragAndDrop: props.enableDragAndDrop, dragDropIdField: props.dragDropIdField, dragDropIndexField: props.dragDropIndexField, list: searchedList, headerField: props.headerField, descriptionField: props.descriptionField, dragAndDropScope: `${props.id}-dnd`, customElement: props.customElement, onDragDrop: async (id, newOrder) => {
                    if (!props.dragDropIndexField) {
                        return;
                    }
                    setIsLoading(true);
                    await ModelAPI.updateById({
                        modelType: props.modelType,
                        id: new ObjectID(id),
                        data: {
                            [props.dragDropIndexField]: newOrder,
                        },
                    });
                    await fetchItems();
                }, titleField: props.titleField, onDelete: props.isDeleteable
                    ? async (item) => {
                        await deleteItem(item);
                    }
                    : undefined, selectedItems: selectedList, onClick: (model) => {
                    if (props.selectMultiple) {
                        // if added to the list, then remove or add to list
                        const isSelected = selectedList.filter((selectedItem) => {
                            var _a, _b;
                            return (((_a = selectedItem._id) === null || _a === void 0 ? void 0 : _a.toString()) === ((_b = model._id) === null || _b === void 0 ? void 0 : _b.toString()));
                        }).length > 0;
                        if (isSelected) {
                            // remove the item.
                            setSelectedList(selectedList.filter((i) => {
                                var _a, _b;
                                return ((_a = i._id) === null || _a === void 0 ? void 0 : _a.toString()) !== ((_b = model._id) === null || _b === void 0 ? void 0 : _b.toString());
                            }));
                        }
                        else {
                            setSelectedList([...selectedList, Object.assign({}, model)]);
                        }
                    }
                    else {
                        setSelectedList([Object.assign({}, model)]);
                    }
                } })),
            props.footer)));
};
export default ModelList;
//# sourceMappingURL=ModelList.js.map