"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DependentLookupEditor = exports.DEBOUNCE_INTERVAL = void 0;
var react_1 = __importStar(require("react"));
var classnames_1 = __importDefault(require("classnames"));
var react_select_1 = require("react-select");
var mdm_sdk_1 = require("@reltio/mdm-sdk");
var ramda_1 = require("ramda");
var ui_i18n_1 = __importDefault(require("ui-i18n"));
var EmptyStub_1 = require("../EmptyStub");
var useDidUpdateEffect_1 = require("../hooks/useDidUpdateEffect");
var ReactSelectDropdownIndicator_1 = require("../ReactSelectDropdownIndicator");
var ReactSelectMenuWithPopper_1 = require("../ReactSelectMenuWithPopper");
var ReactSelectMenuList_1 = require("../ReactSelectMenuList");
var ReactSelectOptionWithCheckIcon_1 = require("../ReactSelectOptionWithCheckIcon");
var ReactSelectLoadMoreButton_1 = require("../ReactSelectLoadMoreButton");
var ReactSelect_1 = require("../ReactSelect");
var MultiValueChip_1 = require("../MultiValueChip");
var useLookupsResolver_1 = require("./useLookupsResolver");
var useDefaultOptions_1 = require("./useDefaultOptions");
var useAutopopulation_1 = require("./useAutopopulation");
var useSavingFocus_1 = require("./useSavingFocus");
var helpers_1 = require("./helpers");
var styles_1 = require("./styles");
var Input = function (props) {
    var _a;
    var styles = (0, styles_1.useStyles)();
    var isCrossedOut = props.selectProps.isCrossedOut;
    return (react_1.default.createElement(react_select_1.components.Input, __assign({}, props, { inputClassName: (0, classnames_1.default)((_a = {}, _a[styles.isCrossedOut] = isCrossedOut, _a)), isHidden: false })));
};
var SelectComponents = {
    IndicatorSeparator: EmptyStub_1.EmptyStub,
    LoadingIndicator: EmptyStub_1.EmptyStub,
    Option: ReactSelectOptionWithCheckIcon_1.ReactSelectOptionWithCheckIcon,
    DropdownIndicator: ReactSelectDropdownIndicator_1.ReactSelectDropdownIndicator,
    Menu: ReactSelectMenuWithPopper_1.ReactSelectMenuWithPopper,
    MenuList: ReactSelectMenuList_1.ReactSelectMenuList,
    MultiValue: MultiValueChip_1.MultiValueChip,
    Input: Input
};
exports.DEBOUNCE_INTERVAL = 400;
var MAX_DEPENDENT_LOOKUP_VALUES = 50;
var DependentLookupEditor = function (_a) {
    var multiple = _a.multiple, value = _a.value, lookupTypeCode = _a.lookupCode, TextFieldProps = _a.TextFieldProps, parents = _a.parents, onChange = _a.onChange, getLookups = _a.getLookups, _b = _a.lookups, lookups = _b === void 0 ? {} : _b, resolveLookups = _a.resolveLookups, fullWidth = _a.fullWidth, disabled = _a.disabled, placeholder = _a.placeholder, _c = _a.max, max = _c === void 0 ? MAX_DEPENDENT_LOOKUP_VALUES : _c, otherProps = __rest(_a, ["multiple", "value", "lookupCode", "TextFieldProps", "parents", "onChange", "getLookups", "lookups", "resolveLookups", "fullWidth", "disabled", "placeholder", "max"]);
    var inputRef = (0, react_1.useRef)(null);
    var selectRef = (0, react_1.useRef)(null);
    var styles = (0, styles_1.useStyles)();
    var _d = (0, react_1.useState)(''), inputValue = _d[0], setInputValue = _d[1];
    var _e = (0, react_1.useState)([]), options = _e[0], setOptions = _e[1];
    var _f = (0, react_1.useState)(1), pageNumber = _f[0], setPageNumber = _f[1];
    var _g = (0, react_1.useState)(false), optionsAreLoading = _g[0], setOptionsAreLoading = _g[1];
    (0, useLookupsResolver_1.useLookupsResolver)({
        lookups: value,
        resolvedValues: lookups[lookupTypeCode],
        resolveLookups: function (codeValues) { return resolveLookups(lookupTypeCode, codeValues); },
        onLookupsResolve: function (lookups) { return onChange(multiple ? lookups : lookups[0]); }
    });
    (0, useSavingFocus_1.useSavingFocus)(selectRef, inputRef, disabled);
    (0, react_1.useEffect)(function () {
        if (!multiple) {
            setInputValue((0, helpers_1.getOptionLabel)(value));
            setOptions(defaultOptions);
            setPageNumber(1);
        }
    }, [value]);
    var handleChange = function (value) {
        markAsTouched();
        onChange(value);
    };
    var handleFocus = function () {
        var _a, _b, _c;
        if (value)
            (_c = (_b = (_a = selectRef.current) === null || _a === void 0 ? void 0 : _a.select) === null || _b === void 0 ? void 0 : _b.inputRef) === null || _c === void 0 ? void 0 : _c.select();
    };
    var resetOptions = function () {
        setPageNumber(1);
        debouncedLoadOptions('', setOptions);
    };
    var restoreSelectedOption = function () {
        if (!multiple && inputValue && inputValue !== (0, helpers_1.getOptionLabel)(value)) {
            setInputValue((0, helpers_1.getOptionLabel)(value));
            resetOptions();
        }
    };
    var handleInputChange = function (newValue, _a) {
        var action = _a.action;
        switch (action) {
            case 'menu-close': {
                restoreSelectedOption();
                break;
            }
            case 'input-blur': {
                if (multiple && inputValue) {
                    setInputValue('');
                    resetOptions();
                    break;
                }
                restoreSelectedOption();
                break;
            }
            case 'input-change': {
                setInputValue(newValue);
                setPageNumber(1);
                debouncedLoadOptions(newValue, setOptions);
                if (!multiple && newValue === '') {
                    handleChange('');
                }
                break;
            }
        }
    };
    var loadOptions = (0, react_1.useCallback)(function (value, pageNumber) {
        if (pageNumber === void 0) { pageNumber = 1; }
        setOptionsAreLoading(true);
        return (parents === null
            ? Promise.resolve([])
            : getLookups({
                type: lookupTypeCode,
                parents: parents,
                displayNamePrefix: value,
                max: max + 1,
                offset: (pageNumber - 1) * max
            }))
            .then(function (buildOptions) { return (0, helpers_1.buildLookupOptions)(buildOptions); })
            .catch(function () { return []; })
            .finally(function () { return setOptionsAreLoading(false); });
    }, [max, lookupTypeCode, parents]);
    var loadMoreOptions = (0, react_1.useCallback)(function () {
        var filterValue = inputValue !== (0, helpers_1.getOptionLabel)(value) ? inputValue : '';
        loadOptions(multiple ? inputValue : filterValue, pageNumber + 1).then(function (buildOptions) {
            setOptions(function (options) { return (0, ramda_1.concat)(options.slice(0, pageNumber * max), buildOptions); });
            setPageNumber(function (page) { return page + 1; });
        });
    }, [max, loadOptions, inputValue, pageNumber]);
    var debouncedLoadOptions = (0, react_1.useCallback)((0, mdm_sdk_1.debounce)(function (value, callback) {
        loadOptions(value).then(function (options) { return callback(options); });
    }, exports.DEBOUNCE_INTERVAL), [loadOptions]);
    var _h = (0, useDefaultOptions_1.useDefaultOptions)(loadOptions), defaultOptions = _h.defaultOptions, initialDefaultOptions = _h.initialDefaultOptions, isLoadingDefaultOptions = _h.isLoading;
    (0, react_1.useEffect)(function () {
        setOptions(defaultOptions);
    }, [defaultOptions]);
    (0, useDidUpdateEffect_1.useDidUpdateEffect)(function () {
        setPageNumber(1);
    }, [lookupTypeCode]);
    var displayedOptions = (0, react_1.useMemo)(function () { return options.slice(0, pageNumber * max); }, [max, options, pageNumber]);
    var showMoreButton = options.length > displayedOptions.length;
    var isEmptyValue = multiple
        ? (0, ramda_1.isEmpty)(value)
        : !(value === null || value === void 0 ? void 0 : value.lookupCode) && !(value === null || value === void 0 ? void 0 : value.value);
    var markAsTouched = (0, useAutopopulation_1.useAutopopulation)({
        initialDefaultOptions: initialDefaultOptions,
        isEmptyValue: isEmptyValue,
        multiple: multiple,
        onChange: onChange
    }).markAsTouched;
    return (react_1.default.createElement(ReactSelect_1.ReactSelect, __assign({}, otherProps, { isMulti: multiple, classes: styles, menuPortalTarget: document.body, menuPlacement: "auto", TextFieldProps: __assign(__assign({}, TextFieldProps), { ref: inputRef, disabled: (TextFieldProps === null || TextFieldProps === void 0 ? void 0 : TextFieldProps.disabled) || disabled }), inputRef: inputRef, innerRef: selectRef, styles: {
            menuPortal: function (base) { return (__assign(__assign({}, base), { zIndex: 1300 })); },
            container: function (base) { return (__assign(__assign({}, base), (fullWidth ? { width: '100%' } : {}))); },
            input: function (base) { return (__assign(__assign({}, base), { visibility: 'visible' })); }
        }, noOptionsMessage: function () {
            return optionsAreLoading && !showMoreButton ? ui_i18n_1.default.text('Loading...') : ui_i18n_1.default.text('No results found');
        }, components: SelectComponents, isClearable: true, isSearchable: true, controlShouldRenderValue: multiple, inputValue: inputValue, filterOption: multiple ? undefined : ramda_1.T, onInputChange: handleInputChange, loadingMessage: function () { return ui_i18n_1.default.text('Loading...'); }, isLoading: !inputValue && isLoadingDefaultOptions, hideSelectedOptions: false, placeholder: placeholder || '', isDisabled: disabled, options: displayedOptions, getOptionValue: (0, ramda_1.either)((0, ramda_1.prop)('value'), (0, ramda_1.prop)('lookupCode')), getOptionLabel: helpers_1.getOptionLabel, onChange: handleChange, onFocus: multiple ? undefined : handleFocus, value: (0, ramda_1.defaultTo)(multiple ? [] : null, value), menuListFooter: showMoreButton && react_1.default.createElement(ReactSelectLoadMoreButton_1.ReactSelectLoadMoreButton, { loading: optionsAreLoading, onClick: loadMoreOptions }) })));
};
exports.DependentLookupEditor = DependentLookupEditor;
