"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
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);
};
Object.defineProperty(exports, "__esModule", { value: true });
var AddButton_1 = require("react-jsonschema-form/lib/components/AddButton");
var React = require("react");
var PatternPropertiesField_1 = require("./PatternPropertiesField");
var utils_1 = require("react-jsonschema-form/lib/utils");
function DefaultObjectFieldTemplate(props) {
    var canExpand = function canExpand() {
        var formData = props.formData, schema = props.schema, uiSchema = props.uiSchema;
        if (!schema.additionalProperties) {
            return false;
        }
        var expandable = utils_1.getUiOptions(uiSchema).expandable;
        if (expandable === false) {
            return expandable;
        }
        if (schema.maxProperties !== undefined) {
            return Object.keys(formData).length < schema.maxProperties;
        }
        return true;
    };
    var TitleField = props.TitleField, DescriptionField = props.DescriptionField;
    return (React.createElement("fieldset", { id: props.idSchema.$id },
        (props.uiSchema["ui:title"] || props.title) && (React.createElement(TitleField, { id: props.idSchema.$id + "__title", title: props.title || props.uiSchema["ui:title"], required: props.required, formContext: props.formContext })),
        props.description && (React.createElement(DescriptionField, { id: props.idSchema.$id + "__description", description: props.description, formContext: props.formContext })),
        props.properties.map(function (prop) { return prop.content; }),
        canExpand() && (React.createElement(AddButton_1.default, { className: "object-property-expand", onClick: props.onAddClick(props.schema), disabled: props.disabled || props.readonly }))));
}
var ObjectField = (function (_super) {
    __extends(ObjectField, _super);
    function ObjectField() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.state = {
            additionalProperties: {},
        };
        _this.onPropertyChange = function (name, addedByAdditionalProperties) {
            if (addedByAdditionalProperties === void 0) { addedByAdditionalProperties = false; }
            return function (value, errorSchema) {
                var _a, _b;
                if (!value && addedByAdditionalProperties) {
                    value = "";
                }
                var newFormData = __assign({}, _this.props.formData, (_a = {}, _a[name] = value, _a));
                _this.props.onChange(newFormData, errorSchema &&
                    _this.props.errorSchema && __assign({}, _this.props.errorSchema, (_b = {}, _b[name] = errorSchema, _b)));
            };
        };
        _this.onDropPropertyClick = function (key) {
            return function (event) {
                event.preventDefault();
                var _a = _this.props, onChange = _a.onChange, formData = _a.formData;
                var copiedFormData = __assign({}, formData);
                delete copiedFormData[key];
                onChange(copiedFormData);
            };
        };
        _this.getAvailableKey = function (preferredKey, formData) {
            var index = 0;
            var newKey = preferredKey;
            while (formData.hasOwnProperty(newKey)) {
                newKey = preferredKey + "-" + ++index;
            }
            return newKey;
        };
        _this.onKeyChange = function (oldValue) {
            return function (value, errorSchema) {
                var _a, _b;
                if (oldValue === value) {
                    return;
                }
                value = _this.getAvailableKey(value, _this.props.formData);
                var newFormData = __assign({}, _this.props.formData);
                var newKeys = (_a = {}, _a[oldValue] = value, _a);
                var keyValues = Object.keys(newFormData).map(function (key) {
                    var _a;
                    var newKey = newKeys[key] || key;
                    return _a = {}, _a[newKey] = newFormData[key], _a;
                });
                var renamedObj = Object.assign.apply(Object, [{}].concat(keyValues));
                _this.props.onChange(renamedObj, errorSchema &&
                    _this.props.errorSchema && __assign({}, _this.props.errorSchema, (_b = {}, _b[value] = errorSchema, _b)));
            };
        };
        _this.handleAddClick = function (schema) { return function () {
            var type = schema.additionalProperties.type;
            var newFormData = __assign({}, _this.props.formData);
            newFormData[_this.getAvailableKey("newKey", newFormData)] = _this.getDefaultValue(type);
            _this.props.onChange(newFormData);
        }; };
        return _this;
    }
    ObjectField.prototype.isRequired = function (name) {
        var schema = this.props.schema;
        return (Array.isArray(schema.required) && schema.required.indexOf(name) !== -1);
    };
    ObjectField.prototype.getDefaultValue = function (type) {
        switch (type) {
            case "string":
                return "New Value";
            case "array":
                return [];
            case "boolean":
                return false;
            case "null":
                return null;
            case "number":
                return 0;
            case "object":
                return {};
            default:
                return "New Value";
        }
    };
    ObjectField.prototype.render = function () {
        var _this = this;
        var _a = this.props, uiSchema = _a.uiSchema, formData = _a.formData, errorSchema = _a.errorSchema, idSchema = _a.idSchema, name = _a.name, required = _a.required, disabled = _a.disabled, readonly = _a.readonly, idPrefix = _a.idPrefix, onBlur = _a.onBlur, onFocus = _a.onFocus, _b = _a.registry, registry = _b === void 0 ? utils_1.getDefaultRegistry() : _b;
        var definitions = registry.definitions, fields = registry.fields, formContext = registry.formContext;
        var SchemaField = fields.SchemaField, TitleField = fields.TitleField, DescriptionField = fields.DescriptionField;
        var schema = utils_1.retrieveSchema(this.props.schema, definitions, formData);
        var title = schema.title === undefined ? name : schema.title;
        var description = uiSchema["ui:description"] || schema.description;
        var orderedProperties;
        try {
            var properties = Object.keys(schema.properties || {});
            orderedProperties = utils_1.orderProperties(properties, uiSchema["ui:order"]);
        }
        catch (err) {
            return (React.createElement("div", null,
                React.createElement("p", { className: "config-error", style: { color: "red" } },
                    "Invalid ",
                    name || "root",
                    " object field configuration:",
                    React.createElement("em", null, err.message),
                    "."),
                React.createElement("pre", null, JSON.stringify(schema))));
        }
        var Template = registry.ObjectFieldTemplate || DefaultObjectFieldTemplate;
        var templateProps = {
            title: uiSchema["ui:title"] || title,
            description: description,
            TitleField: TitleField,
            DescriptionField: DescriptionField,
            properties: orderedProperties.map(function (name) {
                var addedByAdditionalProperties = schema.properties[name].hasOwnProperty(utils_1.ADDITIONAL_PROPERTY_FLAG);
                return {
                    content: (React.createElement(SchemaField, { key: name, name: name, required: _this.isRequired(name), schema: schema.properties[name], uiSchema: addedByAdditionalProperties
                            ? uiSchema.additionalProperties
                            : uiSchema[name], errorSchema: errorSchema[name], idSchema: idSchema[name], idPrefix: idPrefix, formData: formData[name], onKeyChange: _this.onKeyChange(name), onChange: _this.onPropertyChange(name, addedByAdditionalProperties), onBlur: onBlur, onFocus: onFocus, registry: registry, disabled: disabled, readonly: readonly, onDropPropertyClick: _this.onDropPropertyClick })),
                    name: name,
                    readonly: readonly,
                    disabled: disabled,
                    required: required,
                };
            }),
            readonly: readonly,
            disabled: disabled,
            required: required,
            idSchema: idSchema,
            uiSchema: uiSchema,
            schema: schema,
            formData: formData,
            formContext: formContext,
        };
        if (schema.patternProperties) {
            templateProps.properties.push({
                content: (React.createElement(PatternPropertiesField_1.default, { schema: schema, formData: formData, onPropertyChange: this.onPropertyChange, onKeyChange: this.onKeyChange, onDropPropertyClick: this.onDropPropertyClick }))
            });
        }
        return React.createElement(Template, __assign({}, templateProps, { onAddClick: this.handleAddClick }));
    };
    ObjectField.defaultProps = {
        uiSchema: {},
        formData: {},
        errorSchema: {},
        idSchema: {},
        required: false,
        disabled: false,
        readonly: false,
    };
    return ObjectField;
}(React.Component));
exports.default = ObjectField;
