import { __extends } from "tslib";
import { BehaviorSubject } from 'rxjs';
import identity from '../../../utils/identity';
import { BasicModel } from './basic';
import { Some, None, or, isSome, get } from '../maybe';
import { ValidateOption } from '../validate';
import isNil from '../../../utils/isNil';
import uniqueId from '../../../utils/uniqueId';
import { FIELD_ID } from './is';
import { createSentinelSubject } from './sentinel-subject';
import { createFormValidatorRuntimeError } from '../error';
var FieldModel = (function (_super) {
    __extends(FieldModel, _super);
    function FieldModel(defaultValue) {
        var _this = _super.call(this, uniqueId('field-')) || this;
        _this.defaultValue = defaultValue;
        _this._displayName = 'FieldModel';
        _this._value$ = new BehaviorSubject(_this.defaultValue);
        _this._valid$ = new BehaviorSubject(true);
        _this.isTouched = false;
        _this.isCompositing = false;
        _this.normalizeBeforeSubmit = identity;
        _this.owner = null;
        return _this;
    }
    Object.defineProperty(FieldModel.prototype, "value$", {
        get: function () {
            return this._value$;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(FieldModel.prototype, "valid$", {
        get: function () {
            return this._valid$;
        },
        enumerable: false,
        configurable: true
    });
    FieldModel.prototype._getValue$ = function () {
        return this._value$;
    };
    FieldModel.prototype._getValid$ = function () {
        return this._valid$;
    };
    FieldModel.prototype.reset = function () {
        var _this = this;
        this._getValue$().next(or(this.initialValue, function () { return _this.defaultValue; }));
    };
    FieldModel.prototype.clear = function () {
        this.initialValue = None();
        this._getValue$().next(this.defaultValue);
    };
    FieldModel.prototype.clearError = function () {
        this.error$.next(null);
    };
    FieldModel.prototype.initialize = function (value) {
        this.initialValue = Some(value);
        this._getValue$().next(value);
    };
    FieldModel.prototype.getRawValue = function () {
        return this._getValue$().getValue();
    };
    FieldModel.prototype.getSubmitValue = function () {
        var normalizeBeforeSubmit = this.normalizeBeforeSubmit;
        return normalizeBeforeSubmit(this._getValue$().getValue());
    };
    FieldModel.prototype.validate = function (option) {
        var _this = this;
        if (option === void 0) { option = ValidateOption.Default; }
        return this.triggerValidate(option).then(function (maybeError) {
            _this._getValid$().next(isNil(maybeError));
            return maybeError;
        }, function (err) {
            throw createFormValidatorRuntimeError(err);
        });
    };
    FieldModel.prototype.patchValue = function (value) {
        this._getValue$().next(value);
    };
    FieldModel.prototype.pristine = function () {
        var value = this._getValue$().getValue();
        if (isSome(this.initialValue)) {
            return value === get(this.initialValue);
        }
        return value === this.defaultValue;
    };
    FieldModel.prototype.dirty = function () {
        return !this.pristine();
    };
    FieldModel.prototype.touched = function () {
        return this.isTouched;
    };
    FieldModel.prototype.dispose = function () {
        _super.prototype.dispose.call(this);
        this._getValue$().complete();
        this._getValid$().complete();
        this._valid$ = createSentinelSubject(this._displayName, false);
        this._value$ = createSentinelSubject(this._displayName, this.defaultValue);
    };
    return FieldModel;
}(BasicModel));
FieldModel.prototype[FIELD_ID] = true;
export { FieldModel };
