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

import { ISecurityGroup, NewSecurityGroup } from '../security-group.model';
import { SecurityGroupPermissionFormGroup, SecurityGroupPermissionFormService } from './security-group-permission-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 IDashboardComponent for edit and NewDashboardComponentFormGroupInput for create.
 */
type SecurityGroupFormGroupInput = ISecurityGroup | PartialWithRequiredKeyOf<NewSecurityGroup>;

type SecurityGroupFormDefaults = Pick<NewSecurityGroup, 'id'>;

type SecurityGroupFormGroupContent = {
  id: FormControl<ISecurityGroup['id'] | NewSecurityGroup['id']>;
  code: FormControl<ISecurityGroup['code']>;
  name: FormControl<ISecurityGroup['name']>;
  securityGroupPermissions: FormArray<SecurityGroupPermissionFormGroup>;
  version: FormControl<ISecurityGroup['version']>;
};

export type SecurityGroupFormGroup = FormGroup<SecurityGroupFormGroupContent>;

@Injectable({ providedIn: 'root' })
export class SecurityGroupFormService {
  constructor(private fb: FormBuilder, 
			  private securityGroupPermissionFormService: SecurityGroupPermissionFormService ) {} 
			  
  createSecurityGroupFormGroup(securityGroup: SecurityGroupFormGroupInput = { id: null }): SecurityGroupFormGroup {
    const securityGroupRawValue = {
      ...this.getFormDefaults(),
      ...securityGroup,
    };
	
    const items = securityGroup?.securityGroupPermissions??[];
	
    return new FormGroup<SecurityGroupFormGroupContent>({
      id: new FormControl(
        { value: securityGroupRawValue.id, disabled: true },
        {
          nonNullable: true,
          validators: [Validators.required],
        },
      ),
      code: new FormControl(securityGroupRawValue.code, {
        validators: [Validators.required],
      }),
      name: new FormControl(securityGroupRawValue.name, {
        validators: [Validators.required],
      }),
      securityGroupPermissions: new FormArray(items.map(item => this.securityGroupPermissionFormService.createSecurityGroupPermissionFormGroup(item))),
      version: new FormControl(securityGroupRawValue.version),
    });
  }

  getSecurityGroup(form: SecurityGroupFormGroup): ISecurityGroup | NewSecurityGroup {
    return form.getRawValue() as ISecurityGroup | NewSecurityGroup;
  }

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

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