import { CommonModule } from '@angular/common';
import { EventEmitter, Input, Directive, NgZone, ChangeDetectorRef, Optional, ContentChild, Component, ViewEncapsulation, ChangeDetectionStrategy, ContentChildren, Injectable, InjectionToken, Inject, Pipe, NgModule } from '@angular/core';
import { Subject, defer, of } from 'rxjs';
import { take, switchMap, takeUntil, filter } from 'rxjs/operators';
import { FormControl, NgForm, FormGroupDirective } from '@angular/forms';
import { trigger, transition } from '@angular/animations';
import { coerceNumberProperty, coerceBooleanProperty } from '@angular/cdk/coercion';
import { fadeOut, fadeIn } from '@ng-tangram/components/core';

class NtFormFieldControl {
    focus() { }
}

var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
let NtFormLabelWidthDirective = class NtFormLabelWidthDirective {
    constructor() {
        this.widthChange = new EventEmitter();
    }
    set width(value) {
        this._width = coerceNumberProperty(value, 0);
        if (this._width > 0) {
            this.widthChange.next(this._width);
        }
    }
    get width() { return this._width || 120; }
    ngOnDestroy() {
        this.widthChange.next();
        this.widthChange.complete();
    }
};
__decorate([
    Input('ntFormLabelWidth')
], NtFormLabelWidthDirective.prototype, "width", null);
NtFormLabelWidthDirective = __decorate([
    Directive({
        selector: 'form[ntFormLabelWidth]',
    })
], NtFormLabelWidthDirective);

var __decorate$1 = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
let NtFormOrientationDirective = class NtFormOrientationDirective {
    constructor() {
        this.orientationChange = new EventEmitter();
    }
    set orientation(value) {
        this._orientation = value;
        this.orientationChange.next(this._orientation);
    }
    get orientation() { return this._orientation; }
    ngOnDestroy() {
        this.orientationChange.next();
        this.orientationChange.complete();
    }
};
__decorate$1([
    Input('ntFormOrientation')
], NtFormOrientationDirective.prototype, "orientation", null);
NtFormOrientationDirective = __decorate$1([
    Directive({
        selector: 'form[ntFormOrientation]',
    })
], NtFormOrientationDirective);

var __decorate$2 = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
let NtFormFieldComponent = class NtFormFieldComponent {
    constructor(_ngZone, _changeDetectorRef, parentForm, parentFormGroup, _formLabelWidth, _formOrientation) {
        this._ngZone = _ngZone;
        this._changeDetectorRef = _changeDetectorRef;
        this._formLabelWidth = _formLabelWidth;
        this._formOrientation = _formOrientation;
        this._destroy = new Subject();
        this._labelVisible = true;
        this._selfLabelWidth = false;
        this._selfOrientation = false;
        this._markVisible = true;
        this._ngForm = null;
        this._labelStyles = {};
        this._groupStyles = {};
        this._invalid = false;
        this.statusChanges = defer(() => {
            if (this.control && this.ngControl) {
                return this.ngControl.statusChanges ? this.ngControl.statusChanges : of(null);
            }
            return this._ngZone.onStable
                .asObservable()
                .pipe(take(1), switchMap(() => this.statusChanges));
        });
        this._ngForm = parentForm || parentFormGroup;
        if (this._formLabelWidth) {
            this._formLabelWidth.widthChange.pipe(takeUntil(this._destroy), filter(() => !this._selfLabelWidth))
                .subscribe(width => {
                this._labelWidth = width;
                this._setHorizontalStyles();
            });
        }
        if (this._formOrientation) {
            this._formOrientation.orientationChange.pipe(takeUntil(this._destroy), filter(() => !this._selfOrientation))
                .subscribe(orientation => {
                this._orientation = orientation;
                this._setHorizontalStyles();
            });
        }
        this.statusChanges.pipe(takeUntil(this._destroy)).subscribe(() => this._validate());
    }
    set labelVisible(value) { this._labelVisible = coerceBooleanProperty(value); }
    get labelVisible() { return this._labelVisible; }
    set labelWidth(value) {
        this._labelWidth = coerceNumberProperty(value, 0);
        this._selfLabelWidth = this._labelWidth > 0;
        this._setHorizontalStyles();
    }
    get labelWidth() { return this._labelWidth || 120; }
    set orientation(value) {
        this._orientation = value;
        this._selfOrientation = true;
        this._setHorizontalStyles();
    }
    get orientation() { return this._orientation; }
    get horizontal() { return this.orientation === 'horizontal'; }
    get markVisible() { return this._markVisible; }
    set markVisible(value) {
        this._markVisible = coerceBooleanProperty(value);
    }
    get required() {
        if (this.ngControl &&
            this.ngControl.control &&
            this.ngControl.control.validator) {
            const control = new FormControl();
            const validateResult = this.ngControl.control.validator(control);
            return validateResult && validateResult.hasOwnProperty('required');
        }
        if (this.control) {
            return !!this.control.required;
        }
        return false;
    }
    get errors() {
        return this.control.ngControl ? this.control.ngControl.errors : null;
    }
    get ngControl() { return this.control ? this.control.ngControl : null; }
    ngAfterViewInit() {
        if (this._ngForm && this.ngControl) {
            this._ngForm.ngSubmit.pipe(takeUntil(this._destroy)).subscribe(() => this._validate());
        }
    }
    ngOnDestroy() {
        this._destroy.next();
        this._destroy.complete();
    }
    _validate() {
        if (this.ngControl) {
            this._invalid = !!this.ngControl.invalid;
            this._changeDetectorRef.markForCheck();
        }
    }
    _clearValidateMessage() {
        this._invalid = false;
    }
    _setHorizontalStyles() {
        if (this.labelWidth > 0 && this.horizontal) {
            this._labelStyles['width.px'] = this.labelWidth;
            this._groupStyles['margin-left.px'] = this.labelWidth;
        }
        else {
            delete this._labelStyles['width.px'];
            delete this._groupStyles['margin-left.px'];
        }
    }
};
NtFormFieldComponent.ctorParameters = () => [
    { type: NgZone },
    { type: ChangeDetectorRef },
    { type: NgForm, decorators: [{ type: Optional }] },
    { type: FormGroupDirective, decorators: [{ type: Optional }] },
    { type: NtFormLabelWidthDirective, decorators: [{ type: Optional }] },
    { type: NtFormOrientationDirective, decorators: [{ type: Optional }] }
];
__decorate$2([
    Input()
], NtFormFieldComponent.prototype, "label", void 0);
__decorate$2([
    Input()
], NtFormFieldComponent.prototype, "labelVisible", null);
__decorate$2([
    Input()
], NtFormFieldComponent.prototype, "labelWidth", null);
__decorate$2([
    Input()
], NtFormFieldComponent.prototype, "messages", void 0);
__decorate$2([
    Input()
], NtFormFieldComponent.prototype, "orientation", null);
__decorate$2([
    Input()
], NtFormFieldComponent.prototype, "markVisible", null);
__decorate$2([
    ContentChild(NtFormFieldControl)
], NtFormFieldComponent.prototype, "control", void 0);
NtFormFieldComponent = __decorate$2([
    Component({
        selector: 'nt-form-field',
        template: `
    <label class="nt-form-label"
      *ngIf="labelVisible"
      [ngStyle]="_labelStyles"
      [class.required]="markVisible && required">
      {{label}}
    </label>
    <div class="nt-form-group" [ngStyle]="_groupStyles">
      <ng-content></ng-content>
      <span class="form-error is-visible" *ngIf="_invalid && errors" [@fade]="_invalid">
        {{ errors | formError:label:messages }}
      </span>
    </div>
  `,
        animations: [
            trigger('fade', [
                transition('* => false', fadeOut(.15)),
                transition('* => true', fadeIn(.15))
            ])
        ],
        encapsulation: ViewEncapsulation.None,
        changeDetection: ChangeDetectionStrategy.OnPush,
        host: {
            'class': 'nt-form-field',
            '[class.nt-form-error]': '_invalid',
            '[class.nt-form-horizontal]': 'horizontal'
        }
    }),
    __param(2, Optional()),
    __param(3, Optional()),
    __param(4, Optional()),
    __param(5, Optional())
], NtFormFieldComponent);

var __decorate$3 = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param$1 = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
let NtFormAutofocusDirective = class NtFormAutofocusDirective {
    constructor(form, formGroup) {
        this._destory = new Subject();
        this.formContainer = form || formGroup;
    }
    ngAfterContentInit() {
        if (this.formContainer) {
            this.formContainer.ngSubmit
                .pipe(takeUntil(this._destory))
                .subscribe(() => {
                const field = this.fields.find(field => !!field.ngControl && !!field.ngControl.invalid);
                if (field && field.control) {
                    field.control.focus();
                }
            });
        }
    }
    ngOnDestroy() {
        this._destory.next();
        this._destory.complete();
    }
};
NtFormAutofocusDirective.ctorParameters = () => [
    { type: NgForm, decorators: [{ type: Optional }] },
    { type: FormGroupDirective, decorators: [{ type: Optional }] }
];
__decorate$3([
    ContentChildren(NtFormFieldComponent, { descendants: true })
], NtFormAutofocusDirective.prototype, "fields", void 0);
NtFormAutofocusDirective = __decorate$3([
    Directive({
        selector: 'form[ntFormAutofocus]'
    }),
    __param$1(0, Optional()),
    __param$1(1, Optional())
], NtFormAutofocusDirective);

var __decorate$4 = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
const DEFAULT_TEMPLATES = {
    "required": "请填写{0}",
    "email": "{0}不是邮箱格式",
    "min": "{0}必须输入大于{1}的数字",
    "max": "{0}必须输入小于{1}的数字",
    "pattern": "{0}不是合法的数据",
    "maxlength": "{0}长度为最大{1}",
    "minlength": "{0}长度为最小{1}"
};
let NtFormValidationTransformer = class NtFormValidationTransformer {
    transform(errors, label, messages) {
        if (!errors) {
            return '';
        }
        const templates = Object.assign(Object.assign({}, DEFAULT_TEMPLATES), messages);
        if (errors.hasOwnProperty('required')) {
            return this._format(templates['required'], label);
        }
        else if (errors.hasOwnProperty('email')) {
            return this._format(templates['email'], label);
        }
        else if (errors.hasOwnProperty('min')) {
            return this._format(templates['min'], label, errors.min.min);
        }
        else if (errors.hasOwnProperty('max')) {
            return this._format(templates['max'], label, errors.max.max);
        }
        else if (errors.hasOwnProperty('minlength')) {
            return this._format(templates['minlength'], label, errors.minlength.requiredLength);
        }
        else if (errors.hasOwnProperty('maxlength')) {
            return this._format(templates['maxlength'], label, errors.maxlength.requiredLength);
        }
        else if (errors.hasOwnProperty('pattern')) {
            return this._format(templates['pattern'], label);
        }
        else {
            return '';
        }
    }
    _format(template, ...args) {
        return template.replace(/\{(\d+)\}/g, function (match, number) {
            return typeof args[number] !== 'undefined' ? args[number] : match;
        });
    }
};
NtFormValidationTransformer = __decorate$4([
    Injectable()
], NtFormValidationTransformer);
const NT_VALIDATION_TRANSFOMER = new InjectionToken('nt-validation-transformer');

var __decorate$5 = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param$2 = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
let NtFormErrorPipe = class NtFormErrorPipe {
    constructor(_transformer) {
        this._transformer = _transformer;
    }
    transform(value, ...args) {
        return this._transformer.transform(value, ...args);
    }
};
NtFormErrorPipe.ctorParameters = () => [
    { type: undefined, decorators: [{ type: Inject, args: [NT_VALIDATION_TRANSFOMER,] }] }
];
NtFormErrorPipe = __decorate$5([
    Pipe({ name: 'formError' }),
    __param$2(0, Inject(NT_VALIDATION_TRANSFOMER))
], NtFormErrorPipe);

var __decorate$6 = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var NtFormsModule_1;
let NtFormsModule = NtFormsModule_1 = class NtFormsModule {
    static forRoot(transformer) {
        return {
            ngModule: NtFormsModule_1,
            providers: [
                { provide: NT_VALIDATION_TRANSFOMER, useClass: transformer || NtFormValidationTransformer }
            ]
        };
    }
};
NtFormsModule = NtFormsModule_1 = __decorate$6([
    NgModule({
        imports: [CommonModule],
        exports: [
            NtFormFieldComponent,
            NtFormAutofocusDirective,
            NtFormLabelWidthDirective,
            NtFormOrientationDirective,
            NtFormErrorPipe
        ],
        declarations: [
            NtFormFieldComponent,
            NtFormAutofocusDirective,
            NtFormLabelWidthDirective,
            NtFormOrientationDirective,
            NtFormErrorPipe
        ]
    })
], NtFormsModule);

export { DEFAULT_TEMPLATES, NT_VALIDATION_TRANSFOMER, NtFormAutofocusDirective, NtFormErrorPipe, NtFormFieldComponent, NtFormFieldControl, NtFormLabelWidthDirective, NtFormOrientationDirective, NtFormValidationTransformer, NtFormsModule };
//# sourceMappingURL=forms.js.map
