import { Component, Input, OnInit } from '@angular/core';
import { UntypedFormArray, UntypedFormGroup } from '@angular/forms';

@Component({
  selector: 'app-form-errors',
  templateUrl: './form-errors.component.html',
  styleUrls: ['./form-errors.component.scss']
})
export class FormErrorsComponent implements OnInit {
  @Input() formGroup: UntypedFormGroup;
  @Input() maxWidth = 'unset';
  errorMessages: string[];
  visible = false;

  constructor() {
  }

  ngOnInit() {
  }

  hide() {
    this.visible = false;
  }

  setBackendErrors(
    backendErrors: { [field: string]: string | any } | string, nonControlValues = null, formGroup: UntypedFormGroup = null,
  ): boolean {
    if (typeof backendErrors === 'string') {
      this.showError(backendErrors as string);
      return true;
    }

    let errorsDisplayed = false;

    const nonFieldErrors: string[] = [];

    Object.keys(backendErrors).map(fieldName => {
      const control = (formGroup || this.formGroup).get(fieldName);
      if (control && !control.disabled) {
        control.markAsTouched();
        if (control instanceof UntypedFormArray) {
          const formArray = control as UntypedFormArray;
          const arrayErrors = backendErrors[fieldName] as string[];
          let errorIndex = 0;
          for (const arrayControl of formArray.controls) {
            const controlErrors = arrayErrors[errorIndex];
            errorIndex += 1;
            if (controlErrors && !arrayControl.disabled) {
              if (arrayControl instanceof UntypedFormGroup) {
                const arrayFormGroup = arrayControl as UntypedFormGroup;
                const groupErrors = controlErrors as unknown as { [field: string]: string };
                Object.keys(groupErrors).map(groupFieldName => {
                  const groupControl = arrayFormGroup.get(groupFieldName);
                  if (groupControl && !groupControl.disabled) {
                    groupControl.markAsTouched();
                    groupControl.setErrors({
                      backend: true,
                      fleio_error: groupErrors[groupFieldName],
                    });
                    errorsDisplayed = true;
                  }
                });
              } else {
                arrayControl.setErrors({
                  backend: true,
                  fleio_error: controlErrors,
                });
                errorsDisplayed = true;
              }
            }
          }
        }

        if (control instanceof UntypedFormGroup) {
          errorsDisplayed = this.setBackendErrors(
            backendErrors[fieldName], nonControlValues,control
          );
        }

        const errors = {
          backend: true,
          fleio_error: backendErrors[fieldName]
        } as Record<string, any>;
        control.setErrors(errors);
        errorsDisplayed = true;
      } else {
        if (nonControlValues && nonControlValues.hasOwnProperty(fieldName)) {
          // non control values outside the form have been handled, nonFieldErrors should not be updated
          errorsDisplayed = true;
        } else if (fieldName === 'non_field_errors' || fieldName === 'detail') {
          nonFieldErrors.push(`${backendErrors[fieldName]}`);
        } else {
          nonFieldErrors.push(`${fieldName}: ${backendErrors[fieldName]}`);
        }
      }
    });

    if (nonFieldErrors.length > 0) {
      this.showMultipleErrors(nonFieldErrors);
      errorsDisplayed = true;
    }

    return errorsDisplayed;
  }

  showMultipleErrors(errorMessages: string[]) {
    this.errorMessages = errorMessages;
    this.visible = true;
  }

  showError(errorMessage: string) {
    this.showMultipleErrors([errorMessage]);
  }
}
