import { Injectable } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';

import { IVariableCategory, NewVariableCategory } from '../variable-category.model';

/**
 * A partial Type with required key is used as form input.
 */
type PartialWithRequiredKeyOf<T extends { id: unknown }> = Partial<Omit<T, 'id'>> & { id: T['id'] };

/**
 * Type for createFormGroup and resetForm argument.
 * It accepts IVariableCategory for edit and NewVariableCategoryFormGroupInput for create.
 */
type VariableCategoryFormGroupInput = IVariableCategory | PartialWithRequiredKeyOf<NewVariableCategory>;

type VariableCategoryFormDefaults = Pick<NewVariableCategory, 'id'>;

type VariableCategoryFormGroupContent = {
  id: FormControl<IVariableCategory['id'] | NewVariableCategory['id']>;
  code: FormControl<IVariableCategory['code']>;
  name: FormControl<IVariableCategory['name']>;
  description: FormControl<IVariableCategory['description']>;
  version: FormControl<IVariableCategory['version']>;
  variableScope: FormControl<IVariableCategory['variableScope']>;
  hiddenForData: FormControl<IVariableCategory['hiddenForData']>;
  hiddenForFactor: FormControl<IVariableCategory['hiddenForFactor']>;
};

export type VariableCategoryFormGroup = FormGroup<VariableCategoryFormGroupContent>;

@Injectable({ providedIn: 'root' })
export class VariableCategoryFormService {
  createVariableCategoryFormGroup(variableCategory: VariableCategoryFormGroupInput = { id: null }): VariableCategoryFormGroup {
    const variableCategoryRawValue = {
      ...this.getFormDefaults(),
      ...variableCategory,
    };
    return new FormGroup<VariableCategoryFormGroupContent>({
      id: new FormControl(
        { value: variableCategoryRawValue.id, disabled: true },
        {
          nonNullable: true,
          validators: [Validators.required],
        },
      ),
      code: new FormControl(variableCategoryRawValue.code, {
        validators: [Validators.required, Validators.pattern('^[0-9]*$')],
      }),
      name: new FormControl(variableCategoryRawValue.name, {
        validators: [Validators.required],
      }),
      description: new FormControl(variableCategoryRawValue.description, {
        validators: [Validators.required],
      }),
      version: new FormControl(variableCategoryRawValue.version),
      variableScope: new FormControl(variableCategoryRawValue.variableScope),
      hiddenForData: new FormControl(variableCategoryRawValue.hiddenForData),
      hiddenForFactor: new FormControl(variableCategoryRawValue.hiddenForFactor),
    });
  }

  getVariableCategory(form: VariableCategoryFormGroup): IVariableCategory | NewVariableCategory {
    return form.getRawValue() as IVariableCategory | NewVariableCategory;
  }

  resetForm(form: VariableCategoryFormGroup, variableCategory: VariableCategoryFormGroupInput): void {
    const variableCategoryRawValue = { ...this.getFormDefaults(), ...variableCategory };
    form.reset(
      {
        ...variableCategoryRawValue,
        id: { value: variableCategoryRawValue.id, disabled: true },
      } as any /* cast to workaround https://github.com/angular/angular/issues/46458 */,
    );
  }

  private getFormDefaults(): VariableCategoryFormDefaults {
    return {
      id: null,
    };
  }
}
