"use strict";
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 () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.arrayRulesPropType = void 0;
const React = __importStar(require("react"));
const PropTypes = __importStar(require("prop-types"));
const utils_1 = require("../../utils");
const ConditionalUiSchemaField_1 = require("./ConditionalUiSchemaField");
const arrayRulePropType = PropTypes.shape({
    idx: PropTypes.number,
    isLast: PropTypes.number,
    complement: PropTypes.bool
});
exports.arrayRulesPropType = PropTypes.oneOfType([
    ConditionalUiSchemaField_1.rulePropType,
    arrayRulePropType,
    PropTypes.arrayOf(PropTypes.oneOfType([ConditionalUiSchemaField_1.rulePropType, arrayRulePropType]))
]);
class FilterArrayField extends React.Component {
    constructor() {
        super(...arguments);
        this.getOnActiveChange = (idx, prop, callback) => {
            const offset = idx === undefined
                ? 0
                : (idx in this.filteredToOffsets)
                    ? this.filteredToOffsets[idx]
                    : this.filteredTotal;
            this.cachedOnActiveChange(idx === undefined ? undefined : idx + offset, prop, callback);
        };
        this.onChange = (formData) => {
            this.props.onChange(Object.keys(this.filteredIdxs).sort().reduce((_formData, idx) => {
                const updated = [..._formData];
                updated.splice(idx, 0, this.filteredIdxs[idx]);
                return updated;
            }, formData));
        };
    }
    getNextProps(props) {
        if (props.schema.items.type !== "object") {
            throw new Error("Can't use FilterArrayField if items aren't objects");
        }
        this.cache = this.cache || {};
        const { rules, cache } = (0, utils_1.getUiOptions)(props.uiSchema);
        this.filteredIdxs = {};
        this.filteredToOffsets = {};
        this.idxToOffsets = {};
        let filteredCount = 0;
        const store = (idx, item) => {
            this.filteredIdxs[idx] = item;
            filteredCount++;
        };
        const formData = (props.formData || []).filter((item, idx) => {
            let passes;
            if (cache) {
                const { passes: _passes, cache: _cache } = (0, utils_1.checkArrayRules)(rules, { formData: props.formData }, idx, this.cache);
                passes = _passes;
                this.cache = _cache;
                !passes && store(idx, item);
            }
            else {
                passes = (0, utils_1.checkArrayRules)(rules, { formData: props.formData }, idx);
                !passes && store(idx, item);
            }
            if (passes) {
                this.filteredToOffsets[idx - filteredCount] = filteredCount;
                this.filteredToOffsets[`_${idx}`] = filteredCount;
            }
            this.idxToOffsets[idx] = filteredCount;
            return passes;
        });
        this.filteredTotal = filteredCount;
        const errorSchema = Object.keys(props.errorSchema).reduce((errorSchema, idx) => {
            errorSchema[idx - this.idxToOffsets[idx]] = props.errorSchema[idx];
            return errorSchema;
        }, {});
        const innerUiSchema = (0, utils_1.getInnerUiSchema)(props.uiSchema);
        const uiSchema = Object.assign(Object.assign({}, innerUiSchema), { "ui:options": this.getActiveProps(Object.assign(Object.assign({}, (0, utils_1.getUiOptions)(innerUiSchema)), { idxOffsets: this.filteredToOffsets, totalOffset: this.filteredTotal })) });
        return Object.assign(Object.assign({}, props), { formData,
            uiSchema,
            errorSchema, onChange: this.onChange });
    }
    getActiveProps(options) {
        const { onActiveChange, activeIdx } = options;
        if (onActiveChange) {
            if (this.cachedOnActiveChange !== onActiveChange) {
                this.cachedOnActiveChange = onActiveChange;
            }
            options = Object.assign(Object.assign({}, options), { onActiveChange: this.getOnActiveChange });
        }
        if (activeIdx !== undefined) {
            options = Object.assign(Object.assign({}, options), { activeIdx: options.activeIdx - this.idxToOffsets[options.activeIdx] });
        }
        return options;
    }
    render() {
        const SchemaField = this.props.registry.fields.SchemaField;
        return React.createElement(SchemaField, Object.assign({}, this.props, this.getNextProps(this.props)));
    }
}
FilterArrayField.propTypes = {
    uiSchema: PropTypes.shape({
        "ui:options": PropTypes.shape({
            rules: exports.arrayRulesPropType,
            cache: PropTypes.bool
        })
    }),
    schema: PropTypes.shape({
        type: PropTypes.oneOf(["array"])
    }).isRequired,
    formData: PropTypes.array
};
exports.default = FilterArrayField;
