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

import { IUnitType, NewUnitType } from '../unit-type.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 IUnitType for edit and NewUnitTypeFormGroupInput for create.
 */
type UnitTypeFormGroupInput = IUnitType | PartialWithRequiredKeyOf<NewUnitType>;

type UnitTypeFormDefaults = Pick<NewUnitType, 'id'>;

type UnitTypeFormGroupContent = {
  id: FormControl<IUnitType['id'] | NewUnitType['id']>;
  name: FormControl<IUnitType['name']>;
  description: FormControl<IUnitType['description']>;
  valueType: FormControl<IUnitType['valueType']>;
  version: FormControl<IUnitType['version']>;
};

export type UnitTypeFormGroup = FormGroup<UnitTypeFormGroupContent>;

@Injectable({ providedIn: 'root' })
export class UnitTypeFormService {
  createUnitTypeFormGroup(unitType: UnitTypeFormGroupInput = { id: null }): UnitTypeFormGroup {
    const unitTypeRawValue = {
      ...this.getFormDefaults(),
      ...unitType,
    };
    return new FormGroup<UnitTypeFormGroupContent>({
      id: new FormControl(
        { value: unitTypeRawValue.id, disabled: true },
        {
          nonNullable: true,
          validators: [Validators.required],
        },
      ),
      name: new FormControl(unitTypeRawValue.name, {
        validators: [Validators.required],
      }),
      description: new FormControl(unitTypeRawValue.description, {
        validators: [Validators.required],
      }),
      valueType: new FormControl(unitTypeRawValue.valueType, {
        validators: [Validators.required],
      }),
      version: new FormControl(unitTypeRawValue.version),
    });
  }

  getUnitType(form: UnitTypeFormGroup): IUnitType | NewUnitType {
    return form.getRawValue() as IUnitType | NewUnitType;
  }

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

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