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 __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;
};
import * as React from 'react';
import { Form, Message, Header, Table, Label } from 'semantic-ui-react';
import { StringFieldControl, NumberFieldControl, DateFieldControl, BooleanFieldControl, MultilineStringFieldControl } from './Input';
import { useEffect, useState } from 'react';
import { util_setDirty, util_getError, validate, util_isDirty, util_debug, util_setFieldError } from './_utils';
export var createFormEditor = function (cfg) {
    var Editor = function (props) {
        var onChange = props.onChange, valueFromProps = props.value, dirty = props.dirty, ctlProps = __rest(props, ["onChange", "value", "dirty"]);
        var _a = useState(validate(valueFromProps, cfg)), value = _a[0], setValue = _a[1];
        useEffect(function () {
            if (valueFromProps && !util_isDirty(valueFromProps)) {
                util_debug("props changed");
                var v = validate(valueFromProps, cfg);
                setValue(v);
            }
            else {
            }
        }, [valueFromProps]);
        useEffect(function () {
            if (util_isDirty(value)) {
                util_debug("value is changed, propagate to parent..");
                onChange(value);
            }
        }, [value]);
        var handleOnChangeField = function (fieldName, fieldValue) {
            var _a;
            util_debug("changing " + fieldName + " to " + fieldValue);
            var newValue = __assign({}, value, (_a = {}, _a[fieldName] = fieldValue, _a));
            var newValueWithDirty = util_setDirty(util_setFieldError(newValue, fieldName, undefined));
            var newValueValidated = validate(newValueWithDirty, cfg);
            setValue(newValueValidated);
        };
        var handleOnSetError = function (fieldName, error) {
            util_debug("setting error  " + fieldName + " to " + error);
            setValue(util_setFieldError(value, fieldName, error));
        };
        var err = util_getError(value);
        var ErrorCompo = err.hasError && <Message compact negative>
      <Header>{err.errCount} Error{err.errCount > 1 && 's'}</Header>
      <Table compact size="small">
        <Table.Body>
          {err.asList().map(function (errItem, iMsg) {
            return <Table.Row error key={iMsg}>
                <Table.Cell> <b>{errItem.key}</b> </Table.Cell>
                <Table.Cell>{errItem.value}</Table.Cell>
              </Table.Row>;
        })}
        </Table.Body>
      </Table>
    </Message>;
        var FieldControls = value ? cfg.columns.map(function (column, iColumn) {
            var hasError = err.hasErrorOnField(column.name);
            return <Form.Field key={iColumn} inline={column.inline === undefined ? true : column.inline} error={hasError}>
        <Label color={hasError && 'red' || 'black'} basic={!hasError} style={{ border: 'none', width: 150 }}>{column.label || column.name}</Label>
        {getFieldControl(column, value, handleOnChangeField, handleOnSetError)}
      </Form.Field>;
        }) : [];
        var FormEditor = !err.hasBlockingError && <>
      {FieldControls}
    </>;
        if (cfg.formEditorRender) {
            return cfg.formEditorRender({
                ErrorCompo: ErrorCompo,
                FieldControls: FieldControls,
                EditorCompo: FormEditor,
                item: value
            });
        }
        else {
            return <>
        {FormEditor}
        {ErrorCompo}
      </>;
        }
    };
    return Editor;
};
function getFieldControl(column, item, onChangeField, onSetError) {
    var commonProps = {
        style: column.style,
        className: column.className,
        fluid: column.fluid,
        size: column.size,
    };
    if (column.inputType) {
        switch (column.inputType) {
            case 'number':
                return <NumberFieldControl {...commonProps} value={item[column.name]} onSetError={function (err) { return onSetError(column.name, err); }} onChange={function (value) { return onChangeField(column.name, value); }}/>;
            case 'date':
                return <DateFieldControl {...commonProps} value={item[column.name]} onSetError={function (err) { return onSetError(column.name, err); }} onChange={function (value) { return onChangeField(column.name, value); }}/>;
            case 'boolean':
                return <BooleanFieldControl {...commonProps} value={item[column.name]} onSetError={function (err) { return onSetError(column.name, err); }} onChange={function (value) { return onChangeField(column.name, value); }}/>;
            case 'multilinestring':
                return <MultilineStringFieldControl {...commonProps} value={item[column.name]} onSetError={function (err) { return onSetError(column.name, err); }} onChange={function (value) { return onChangeField(column.name, value); }}/>;
            case 'string':
            default:
                return <StringFieldControl {...commonProps} value={item[column.name]} onSetError={function (err) { return onSetError(column.name, err); }} onChange={function (value) { return onChangeField(column.name, value); }}/>;
        }
    }
    if (column.customControl) {
        var Control = column.customControl;
        return <Control value={item[column.name]} onSetError={function (err) { return onSetError(column.name, err); }} onChange={function (value) { return onChangeField(column.name, value); }} {...commonProps}/>;
    }
    return <div>NO CONTROL CONFIGURED, provide inputType or customControl</div>;
}
