import { useMemo } from 'react';
import { FieldArrayModel, FormStrategy, isModelRef, isFieldArrayModel, } from './models';
import { useFormContext } from './context';
import { useDestroyOnUnmount } from './utils';
import { isSome, get } from './maybe';
import { createModelNotFoundError, createUnexpectedModelTypeError, } from './error';
import { useObservableEagerState } from 'observable-hooks';
function useArrayModel(field, parent, strategy, defaultValue) {
    var model = useMemo(function () {
        var model;
        if (typeof field === 'string') {
            var m = parent.get(field);
            if (strategy === FormStrategy.View) {
                if (!m || !isFieldArrayModel(m)) {
                    var potential = parent.getPatchedValue(field);
                    var v = defaultValue;
                    if (isSome(potential)) {
                        var inner = get(potential);
                        if (Array.isArray(inner)) {
                            v = inner;
                        }
                    }
                    model = new FieldArrayModel(null, v);
                    parent.registerChild(field, model);
                }
                else {
                    model = m;
                }
            }
            else {
                if (!m) {
                    throw createModelNotFoundError(field);
                }
                else if (!isFieldArrayModel(m)) {
                    throw createUnexpectedModelTypeError(field, 'FieldArrayModel', m);
                }
                else {
                    model = m;
                }
            }
        }
        else if (isModelRef(field)) {
            var m = field.getModel();
            if (!m || !isFieldArrayModel(m)) {
                var v = defaultValue;
                if (isSome(field.patchedValue)) {
                    var inner = get(field.patchedValue);
                    if (Array.isArray(inner)) {
                        v = inner;
                    }
                }
                else if (isSome(field.initialValue)) {
                    var inner = get(field.initialValue);
                    if (Array.isArray(inner)) {
                        v = inner;
                    }
                }
                model = new FieldArrayModel(null, v);
            }
            else {
                model = m;
            }
        }
        else {
            model = field;
        }
        return model;
    }, [field, parent, strategy]);
    return model;
}
export function useFieldArray(field, validators, defaultValue) {
    var _a;
    if (validators === void 0) { validators = []; }
    if (defaultValue === void 0) { defaultValue = []; }
    var _b = (_a = useFormContext(typeof field !== 'string')) !== null && _a !== void 0 ? _a : {}, parent = _b.parent, strategy = _b.strategy;
    var model = useArrayModel(field, parent, strategy, defaultValue);
    if (strategy === FormStrategy.View &&
        (typeof field === 'string' || isModelRef(field))) {
        model.validators = validators;
    }
    useObservableEagerState(model.children$);
    useObservableEagerState(model.error$);
    useDestroyOnUnmount(field, model, parent);
    return model;
}
