"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;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const React = __importStar(require("react"));
const ReactContext_1 = __importDefault(require("../../ReactContext"));
const PropTypes = __importStar(require("prop-types"));
const utils_1 = require("../../utils");
const deepmerge_1 = __importDefault(require("deepmerge"));
const ArrayFieldTemplate_1 = require("../templates/ArrayFieldTemplate");
const ArrayField_1 = require("./ArrayField");
const SingleActiveArrayField_1 = require("./SingleActiveArrayField");
class MultiActiveArrayField extends React.Component {
    constructor(props) {
        super(props);
        // these are required by the AccordionArrayFieldTemplate
        this.deleteButtonRefs = {};
        this.deleteButtonRefSetters = {};
        this.getInitialActiveIdx = (props) => {
            const { formData } = props;
            const formDataLength = (formData || []).length;
            return [...Array(formDataLength).keys()];
        };
        this.onActiveChange = (idx, prop, callback) => {
            let newActiveIdx;
            if (this.state.activeIdx.includes(idx)) {
                newActiveIdx = this.state.activeIdx.filter(i => i !== idx);
            }
            else {
                newActiveIdx = [...this.state.activeIdx, idx];
            }
            this.setState({ activeIdx: newActiveIdx }, callback);
        };
        this.onDelete = (item) => (e) => {
            const idx = item.index;
            const newActiveIdx = this.state.activeIdx.filter(i => i !== idx).map(i => i > idx ? i - 1 : i);
            this.setState({ activeIdx: newActiveIdx });
            item.onDropIndexClick(item.index)(e);
        };
        this.buttonDefinitions = {
            add: {
                callback: () => this.onActiveChange((this.props.formData || []).length)
            },
            addPredefined: {
                callback: () => this.onActiveChange((this.props.formData || []).length)
            },
            copy: {
                fn: () => (...params) => {
                    const { formData = [] } = this.props;
                    const idx = this.state.activeIdx.length > 0 ?
                        this.state.activeIdx[this.state.activeIdx.length - 1] :
                        formData.length - 1;
                    (0, ArrayFieldTemplate_1.beforeAdd)(this.props, idx + 1);
                    this.props.onChange([
                        ...formData.slice(0, idx + 1),
                        (0, ArrayField_1.copyItemFunction)(this, formData[idx])(...params),
                        ...formData.slice(idx + 1)
                    ]);
                },
                callback: () => {
                    const idx = this.state.activeIdx !== undefined ?
                        this.state.activeIdx[this.state.activeIdx.length - 1] :
                        (this.props.formData || []).length - 1;
                    this.onActiveChange(idx + 1);
                },
                rules: {
                    minLength: 1
                }
            }
        };
        this.deleteButtonRefs = {};
        this.deleteButtonRefSetters = {};
        this.state = Object.assign({ activeIdx: this.getInitialActiveIdx(props) }, this.getStateFromProps(props));
    }
    UNSAFE_componentWillReceiveProps(props) {
        this.setState(this.getStateFromProps(props));
    }
    getStateFromProps(props) {
        let activeIdx;
        const options = (0, utils_1.getUiOptions)(props.uiSchema);
        if ("activeIdx" in options) {
            activeIdx = options.activeIdx;
        }
        else if ((props.formData || []).length > 0 && (this.props.formData || []).length === 0) {
            activeIdx = [...Array((props.formData || []).length).keys()];
        }
        if (!activeIdx && this.props && props.idSchema.$id !== this.props.idSchema.$id) {
            activeIdx = this.getInitialActiveIdx(props);
        }
        return activeIdx ? { activeIdx } : null;
    }
    render() {
        const { renderer = "accordion" } = (0, utils_1.getUiOptions)(this.props.uiSchema);
        let ArrayFieldTemplate = undefined;
        switch (renderer) {
            case "accordion":
                ArrayFieldTemplate = SingleActiveArrayField_1.AccordionArrayFieldTemplate;
                break;
            default:
                throw new Error(`Unknown renderer '${renderer}' for MultiActiveArrayField`);
        }
        const formContext = Object.assign(Object.assign({}, this.props.formContext), { this: this, activeIdx: this.state.activeIdx });
        const { registry: { fields: { ArrayField } } } = this.props;
        const { buttons = [], buttonDefinitions } = (0, utils_1.getUiOptions)(this.props.uiSchema);
        let uiSchema = Object.assign(Object.assign({}, this.props.uiSchema), { "ui:field": undefined, "ui:classNames": undefined, "ui:options": Object.assign(Object.assign({}, (0, utils_1.getUiOptions)(this.props.uiSchema)), { buttons, buttonDefinitions: buttonDefinitions
                    ? (0, deepmerge_1.default)(this.buttonDefinitions, buttonDefinitions)
                    : this.buttonDefinitions }) });
        uiSchema["ui:ArrayFieldTemplate"] = ArrayFieldTemplate;
        return (React.createElement(ArrayField, Object.assign({}, this.props, { formContext: formContext, registry: Object.assign(Object.assign({}, this.props.registry), { formContext }), schema: this.props.schema, uiSchema: uiSchema, idSchema: this.props.idSchema, errorSchema: this.props.errorSchema, onChange: this.props.onChange, onBlur: this.props.onBlur, onFocus: this.props.onFocus, disabled: this.props.disabled, readonly: this.props.readonly, name: this.props.name })));
    }
}
MultiActiveArrayField.contextType = ReactContext_1.default;
MultiActiveArrayField.propTypes = {
    uiSchema: PropTypes.shape({
        "ui:options": PropTypes.shape({
            renderer: PropTypes.oneOf(["accordion"]),
            activeIdx: PropTypes.arrayOf(PropTypes.number)
        })
    }),
    schema: PropTypes.shape({
        type: PropTypes.oneOf(["array"])
    }).isRequired,
    formData: PropTypes.array
};
exports.default = MultiActiveArrayField;
