/**
 * amis-ui v6.14.0-beta.1
 * Copyright 2018-2025 fex
 */

'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var tslib = require('tslib');
var React = require('react');
var hoistNonReactStatic = require('hoist-non-react-statics');
var debounce = require('lodash/debounce');
var mobxStateTree = require('mobx-state-tree');
var amisCore = require('amis-core');
var mobx = require('mobx');
var WithStore = require('./WithStore.js');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
var hoistNonReactStatic__default = /*#__PURE__*/_interopDefaultLegacy(hoistNonReactStatic);
var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce);

var __react_jsx__ = require('react');
var _J$X_ = (__react_jsx__["default"] || __react_jsx__).createElement;
(__react_jsx__["default"] || __react_jsx__).Fragment;
var Store = mobxStateTree.types
    .model('RemoteConfigStore')
    .props({
    fetching: false,
    errorMsg: '',
    config: mobxStateTree.types.frozen(),
    data: mobxStateTree.types.frozen({})
})
    .actions(function (self) {
    var component = undefined;
    var fetchCancel = null;
    var load = mobxStateTree.flow(function (env, api, ctx, config) {
        var ret, data, options, e_1;
        var _a;
        if (config === void 0) { config = {}; }
        return tslib.__generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    _b.trys.push([0, 2, 3, 4]);
                    if (fetchCancel) {
                        fetchCancel === null || fetchCancel === void 0 ? void 0 : fetchCancel('remote load request cancelled.');
                        fetchCancel = null;
                        self.fetching = false;
                    }
                    if (self.fetching) {
                        return [2 /*return*/];
                    }
                    self.fetching = true;
                    return [4 /*yield*/, env.fetcher(api, ctx, {
                            cancelExecutor: function (executor) { return (fetchCancel = executor); }
                        })];
                case 1:
                    ret = _b.sent();
                    fetchCancel = null;
                    if (!mobxStateTree.isAlive(self)) {
                        return [2 /*return*/];
                    }
                    if (ret.ok) {
                        data = amisCore.normalizeApiResponseData(ret.data);
                        options = config.adaptor
                            ? config.adaptor(data, component.props)
                            : data;
                        self.setConfig(options, config, 'remote');
                        (_a = config.afterLoad) === null || _a === void 0 ? void 0 : _a.call(config, data, self.config, component.props);
                        return [2 /*return*/, ret];
                    }
                    else {
                        throw new Error(ret.msg || 'fetch error');
                    }
                case 2:
                    e_1 = _b.sent();
                    mobxStateTree.isAlive(self) && (self.errorMsg = e_1.message);
                    return [3 /*break*/, 4];
                case 3:
                    mobxStateTree.isAlive(self) && (self.fetching = false);
                    return [7 /*endfinally*/];
                case 4: return [2 /*return*/];
            }
        });
    });
    return {
        setComponent: function (c) {
            component = c;
        },
        load: load,
        setData: function (data) {
            self.data = data || {};
        },
        setConfig: function (options, config, motivation) {
            if (config.normalizeConfig) {
                options =
                    config.normalizeConfig(options, self.config, component.props, motivation) || options;
            }
            self.config = options;
        }
    };
});
function withRemoteConfig(config) {
    if (config === void 0) { config = {}; }
    return function (ComposedComponent) {
        var _a;
        var result = hoistNonReactStatic__default["default"](WithStore.withStore(function () { return Store.create(); })((_a = /** @class */ (function (_super) {
                tslib.__extends(class_1, _super);
                function class_1(props) {
                    var _this = this;
                    var _a;
                    _this = _super.call(this, props) || this;
                    _this.toDispose = [];
                    _this.loadOptions = debounce__default["default"](_this.loadAutoComplete.bind(_this), 250, {
                        trailing: true,
                        leading: false
                    });
                    _this.setConfig = _this.setConfig.bind(_this);
                    _this.childRef = _this.childRef.bind(_this);
                    props.store.setComponent(_this);
                    _this.deferLoadConfig = _this.deferLoadConfig.bind(_this);
                    (_a = props.remoteConfigRef) === null || _a === void 0 ? void 0 : _a.call(props, _this);
                    props.store.setData(props.data);
                    _this.syncConfig();
                    return _this;
                }
                class_1.prototype.componentDidMount = function () {
                    var _this = this;
                    var env = this.props.env || this.context;
                    var _a = this.props, store = _a.store, data = _a.data;
                    var source = this.props[config.sourceField || 'source'];
                    if (amisCore.isPureVariable(source)) {
                        this.toDispose.push(mobx.reaction(function () {
                            return amisCore.resolveVariableAndFilter(source, store.data, '| raw');
                        }, function () { return _this.syncConfig(); }, 
                        // 当nav配置source: "${amisStore.app.portalNavs}"时，切换页面就会触发source更新
                        // 因此这里增加这个配置 数据源完全不相等情况下再执行loadConfig
                        // 否则数据源重置 保存不了展开状态 就会始终是手风琴模式了
                        { equals: mobx.comparer.structural }));
                    }
                    else if (env && amisCore.isEffectiveApi(source, data)) {
                        this.loadConfig();
                        source.autoRefresh !== false &&
                            this.toDispose.push(mobx.reaction(function () {
                                var api = amisCore.normalizeApi(source);
                                return api.trackExpression
                                    ? amisCore.tokenize(api.trackExpression, store.data)
                                    : amisCore.buildApi(api, store.data, {
                                        ignoreData: true
                                    }).url;
                            }, function () { return _this.loadConfig(); }));
                    }
                };
                class_1.prototype.componentDidUpdate = function (prevProps) {
                    var props = this.props;
                    if (props.data !== prevProps.data) {
                        props.store.setData(props.data);
                    }
                };
                class_1.prototype.componentWillUnmount = function () {
                    var _a, _b;
                    this.toDispose.forEach(function (fn) { return fn(); });
                    this.toDispose = [];
                    (_b = (_a = this.props).remoteConfigRef) === null || _b === void 0 ? void 0 : _b.call(_a, undefined);
                    this.loadOptions.cancel();
                };
                class_1.prototype.loadConfig = function (ctx) {
                    if (ctx === void 0) { ctx = this.props.data; }
                    return tslib.__awaiter(this, void 0, void 0, function () {
                        var env, _a, store, data, source;
                        return tslib.__generator(this, function (_b) {
                            switch (_b.label) {
                                case 0:
                                    env = this.props.env || this.context;
                                    _a = this.props, store = _a.store, data = _a.data;
                                    source = this.props[config.sourceField || 'source'];
                                    // source: ${nav}、source: ${online ? '/api/v1' : '/api/v2'}
                                    // 如果是配置source: ${nav} isEffectiveApi也会认为是api 发出一个无效请求
                                    if (amisCore.isPureVariable(source)) {
                                        source = amisCore.resolveVariableAndFilter(source, data, '| raw');
                                    }
                                    if (!(env && amisCore.isEffectiveApi(source, ctx))) return [3 /*break*/, 2];
                                    return [4 /*yield*/, store.load(env, source, ctx, config)];
                                case 1:
                                    _b.sent();
                                    _b.label = 2;
                                case 2: return [2 /*return*/];
                            }
                        });
                    });
                };
                class_1.prototype.loadAutoComplete = function (input) {
                    var env = this.props.env || this.context;
                    var _a = this.props, autoComplete = _a.autoComplete, data = _a.data, store = _a.store;
                    if (!env || !env.fetcher) {
                        throw new Error('fetcher is required');
                    }
                    var ctx = amisCore.createObject(data, {
                        term: input,
                        value: input
                    });
                    if (!amisCore.isEffectiveApi(autoComplete, ctx)) {
                        return Promise.resolve({
                            options: []
                        });
                    }
                    return store.load(env, autoComplete, ctx, config);
                };
                class_1.prototype.setConfig = function (value, ctx) {
                    var store = this.props.store;
                    store.setConfig(value, config, ctx);
                };
                class_1.prototype.syncConfig = function () {
                    var _a = this.props, store = _a.store, data = _a.data;
                    var source = this.props[config.sourceField || 'source'];
                    if (amisCore.isPureVariable(source)) {
                        source =
                            amisCore.resolveVariableAndFilter(source, data, '| raw') || [];
                        if (amisCore.isEffectiveApi(source, data)) {
                            this.loadConfig();
                        }
                        else {
                            store.setConfig(source, config, 'syncConfig');
                        }
                    }
                    else if (amisCore.isObject(source) && !source.method) {
                        store.setConfig(source, config, 'syncConfig');
                    }
                };
                class_1.prototype.deferLoadConfig = function (item) {
                    var _a, _b;
                    return tslib.__awaiter(this, void 0, void 0, function () {
                        var _c, store, data, deferApi, source, env, indexes, ret, response, e_2, ret2;
                        return tslib.__generator(this, function (_d) {
                            switch (_d.label) {
                                case 0:
                                    _c = this.props, store = _c.store, data = _c.data, deferApi = _c.deferApi;
                                    source = this.props[config.sourceField || 'source'];
                                    env = this.props.env || this.context;
                                    indexes = amisCore.findTreeIndex(store.config, function (a) { return a === item; });
                                    ret = (_a = config.beforeDeferLoad) === null || _a === void 0 ? void 0 : _a.call(config, item, indexes, store.config, this.props);
                                    ret && store.setConfig(ret, config, 'before-defer-load');
                                    _d.label = 1;
                                case 1:
                                    _d.trys.push([1, 3, , 4]);
                                    if (!amisCore.isEffectiveApi(item.deferApi || deferApi || source)) {
                                        throw new Error('deferApi is required');
                                    }
                                    return [4 /*yield*/, env.fetcher(item.deferApi || deferApi || source, amisCore.createObject(data, item))];
                                case 2:
                                    response = _d.sent();
                                    return [3 /*break*/, 4];
                                case 3:
                                    e_2 = _d.sent();
                                    response = {
                                        ok: false,
                                        msg: e_2.message,
                                        status: 500,
                                        data: undefined
                                    };
                                    return [3 /*break*/, 4];
                                case 4: return [4 /*yield*/, ((_b = config.afterDeferLoad) === null || _b === void 0 ? void 0 : _b.call(config, item, indexes, // 只能假定还是那个 index 了
                                    response, store.config, this.props))];
                                case 5:
                                    ret2 = _d.sent();
                                    ret2 && store.setConfig(ret2, config, 'after-defer-load');
                                    return [2 /*return*/];
                            }
                        });
                    });
                };
                class_1.prototype.childRef = function (ref) {
                    while (ref && ref.getWrappedInstance) {
                        ref = ref.getWrappedInstance();
                    }
                    this.ref = ref;
                };
                class_1.prototype.getWrappedInstance = function () {
                    return this.ref;
                };
                class_1.prototype.render = function () {
                    var _a;
                    var store = this.props.store;
                    var env = this.props.env || this.context;
                    var injectedProps = {
                        config: store.config,
                        loading: store.fetching,
                        deferLoad: this.deferLoadConfig,
                        updateConfig: this.setConfig
                    };
                    var _b = this.props; _b.remoteConfigRef; var autoComplete = _b.autoComplete, rest = tslib.__rest(_b, ["remoteConfigRef", "autoComplete"]);
                    var refConfig = ((_a = ComposedComponent.prototype) === null || _a === void 0 ? void 0 : _a.isReactComponent) ||
                        ComposedComponent.$$typeof ===
                            Symbol.for('react.forward_ref')
                        ? { ref: this.childRef }
                        : { forwardedRef: this.childRef };
                    return (_J$X_(ComposedComponent, tslib.__assign({}, rest, (env && amisCore.isEffectiveApi(autoComplete) && this.loadOptions
                        ? { loadOptions: this.loadOptions }
                        : {}), (config.injectedPropsFilter
                        ? config.injectedPropsFilter(injectedProps, this.props)
                        : injectedProps), refConfig)));
                };
                return class_1;
            }(React__default["default"].Component)),
            _a.displayName = "WithRemoteConfig(".concat(ComposedComponent.displayName || ComposedComponent.name, ")"),
            _a.ComposedComponent = ComposedComponent,
            _a.contextType = amisCore.EnvContext,
            _a)), ComposedComponent);
        return result;
    };
}

exports.Store = Store;
exports.withRemoteConfig = withRemoteConfig;
