import {
  AfterContentInit,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  ContentChild,
  Input,
  OnDestroy,
  TemplateRef
} from '@angular/core';
import {
  AbstractControl,
  FormControlDirective,
  FormControlName,
  NgControl,
  NgModel
} from '@angular/forms';
import { Subscription } from 'rxjs';
import { IFormControlStatus } from './form.type';

@Component({
  selector: 'bixi-form-item',
  exportAs: 'bixiFormItem',
  host: { '[class.bixi-form-item]': 'true' },
  template: `
  <nz-form-item>
    <nz-form-label
      [nzRequired]="required"
      [nzSpan]="ls"
      [nzNoColon]="label ? noColon : true"
      [nzFor]="for">
      {{label}}
    </nz-form-label>
    <nz-form-control
      [nzValidateStatus]="status"
      [nzSpan]="cs"
      [nzHasFeedback]="hasFeedback"
      [nzExtra]="extra"
      [nzSuccessTip]="successTip"
      [nzWarningTip]="warningTip"
      [nzErrorTip]="errorTip"
      [nzValidatingTip]="validatingTip"
    >
      <ng-content></ng-content>
    </nz-form-control>
   </nz-form-item >
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class BixiFormItemComponent implements OnDestroy, AfterContentInit {
  private validateChanges: Subscription = Subscription.EMPTY;

  constructor(private cdr: ChangeDetectorRef) { }

  status: IFormControlStatus | null;
  _validateStatus: IFormControlStatus | null;
  // label
  @Input() required = false;
  @Input() label: string;
  @Input() noColon = false;
  @Input() for: string;

  // control
  @Input()
  set validateStatus(status: IFormControlStatus | null) {
    this.status = status;
    this._validateStatus = status;
  }

  get validateStatus() {
    return this._validateStatus;
  }

  @Input() hasFeedback = false;
  @Input() extra?: string | TemplateRef<void>;
  @Input() successTip?: string | TemplateRef<{ $implicit: AbstractControl | NgModel }>;
  @Input() warningTip?: string | TemplateRef<{ $implicit: AbstractControl | NgModel }>;
  @Input() errorTip?: string | TemplateRef<{ $implicit: AbstractControl | NgModel }>;
  @Input() validatingTip?: string | TemplateRef<{ $implicit: AbstractControl | NgModel }>;
  // TODO: 9.0 feature
  // @Input() autoTips: Record<string, Record<string, string>> = {};
  // @Input() disableAutoTips: boolean | 'default' = 'default';

  @ContentChild(NgControl, { static: false }) validateControl?: FormControlName | FormControlDirective;

  // layout
  @Input() ls: number = 6;
  @Input() cs: number = 18;


  // fix zorro detect bug
  ngAfterContentInit() {
    if (this.validateControl && this.validateControl.statusChanges) {
      this.validateChanges = this.validateControl.statusChanges.subscribe((status) => {
        if (this.validateStatus) return;
        this.status = null;
        if (this.validateControl && !this.validateControl.dirty) {
          this.cdr.markForCheck();
          return;
        }
        switch (status) {
          case 'VALID': {
            break;
          }
          case 'INVALID': {
            this.status = 'error';
            break;
          }
          case 'DISABLED': {
            break;
          }
          case 'PENDING': {
            this.status = 'validating';
            break;
          }
        }
        this.cdr.markForCheck();
      });
    }
  }

  ngOnDestroy() {
    this.validateChanges.unsubscribe();
  }
}
