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

import { IVariableClassType, NewVariableClassType } from '../variable-class-type.model';
import { VariableClassFormGroup, VariableClassFormService } from '../../variable-class/update/variable-class-form.service';

/**
 * 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 IVariableClassType for edit and NewVariableClassTypeFormGroupInput for create.
 */
type VariableClassTypeFormGroupInput = IVariableClassType | PartialWithRequiredKeyOf<NewVariableClassType>;

type VariableClassTypeFormDefaults = Pick<NewVariableClassType, 'id'>;

type VariableClassTypeFormGroupContent = {
  id: FormControl<IVariableClassType['id'] | NewVariableClassType['id']>;
  code: FormControl<IVariableClassType['code']>;
  name: FormControl<IVariableClassType['name']>;
  description: FormControl<IVariableClassType['description']>;
  label: FormControl<IVariableClassType['label']>;
  variableClasses: FormArray<VariableClassFormGroup>;
  version: FormControl<IVariableClassType['version']>;
};

export type VariableClassTypeFormGroup = FormGroup<VariableClassTypeFormGroupContent>;

@Injectable({ providedIn: 'root' })
export class VariableClassTypeFormService {
  constructor(private fb: FormBuilder, 
			  private variableClassFormService: VariableClassFormService ) {} 
			  
  createVariableClassTypeFormGroup(variableClassType: VariableClassTypeFormGroupInput = { id: null }): VariableClassTypeFormGroup {
    const variableClassTypeRawValue = {
      ...this.getFormDefaults(),
      ...variableClassType,
    };
	
	const items = variableClassType?.variableClasses??[];
	
    return new FormGroup<VariableClassTypeFormGroupContent>({
      id: new FormControl(
        { value: variableClassTypeRawValue.id, disabled: true },
        {
          nonNullable: true,
          validators: [Validators.required],
        },
      ),
      code: new FormControl(variableClassTypeRawValue.code, {
        validators: [Validators.required],
      }),
      name: new FormControl(variableClassTypeRawValue.name, {
        validators: [Validators.required],
      }),
      description: new FormControl(variableClassTypeRawValue.description, {
        validators: [Validators.required],
      }),
      label: new FormControl(variableClassTypeRawValue.label, {
        validators: [Validators.required],
      }),
      variableClasses: new FormArray(items.map(item => this.variableClassFormService.createVariableClassFormGroup(item))),
      version: new FormControl(variableClassTypeRawValue.version),
    });
  }

  getVariableClassType(form: VariableClassTypeFormGroup): IVariableClassType | NewVariableClassType {
    return form.getRawValue() as IVariableClassType | NewVariableClassType;
  }

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

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