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

import { IDashboardComponent, NewDashboardComponent } from '../dashboard-component.model';
import { DashboardComponentDetailFormGroup, DashboardComponentDetailFormService } from './dashboard-component-detail-form.service';
import { DashboardComponentOrganizationFormGroup, DashboardComponentOrganizationFormService } from './dashboard-component-organization-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 DashboardComponentFormGroupInput = IDashboardComponent | PartialWithRequiredKeyOf<NewDashboardComponent>;

type DashboardComponentFormDefaults = Pick<NewDashboardComponent, 'id' | 'isExportable'>;

type DashboardComponentFormGroupContent = {
  id: FormControl<IDashboardComponent['id'] | NewDashboardComponent['id']>;
  code: FormControl<IDashboardComponent['code']>;
  name: FormControl<IDashboardComponent['name']>;
  type: FormControl<IDashboardComponent['type']>;
  view: FormControl<IDashboardComponent['view']>;
  chartType: FormControl<IDashboardComponent['chartType']>;
  description: FormControl<IDashboardComponent['description']>;
  isActive: FormControl<IDashboardComponent['isActive']>;
  isExportable: FormControl<IDashboardComponent['isExportable']>;
  dashboardComponentDetails: FormArray<DashboardComponentDetailFormGroup>;
  dashboardComponentOrganizations: FormArray<DashboardComponentOrganizationFormGroup>;
  version: FormControl<IDashboardComponent['version']>;
};

export type DashboardComponentFormGroup = FormGroup<DashboardComponentFormGroupContent>;

@Injectable({ providedIn: 'root' })
export class DashboardComponentFormService {
  constructor(private fb: FormBuilder, 
	            private dashboardComponentDetailFormService: DashboardComponentDetailFormService,
              private dashboardComponentOrganizationFormService: DashboardComponentOrganizationFormService ) {} 
			  
  createDashboardComponentFormGroup(dashboardComponent: DashboardComponentFormGroupInput = { id: null }): DashboardComponentFormGroup {
    const dashboardComponentRawValue = {
      ...this.getFormDefaults(),
      ...dashboardComponent,
    };
	
    const items = dashboardComponent?.dashboardComponentDetails??[];
	
    return new FormGroup<DashboardComponentFormGroupContent>({
      id: new FormControl(
        { value: dashboardComponentRawValue.id, disabled: true },
        {
          nonNullable: true,
          validators: [Validators.required],
        },
      ),
      code: new FormControl(dashboardComponentRawValue.code, {
        validators: [Validators.required],
      }),
      name: new FormControl(dashboardComponentRawValue.name, {
        validators: [Validators.required],
      }),
      type: new FormControl(dashboardComponentRawValue.type, {
        validators: [Validators.required],
      }),
      view: new FormControl(dashboardComponentRawValue.view),
      chartType: new FormControl(dashboardComponentRawValue.chartType),
      description: new FormControl(dashboardComponentRawValue.description),
      isActive: new FormControl(dashboardComponentRawValue.isActive),
      isExportable: new FormControl(dashboardComponentRawValue.isExportable, {
        validators: [Validators.required],
      }),
      dashboardComponentDetails: new FormArray(items.map(item => this.dashboardComponentDetailFormService.createDashboardComponentDetailFormGroup(item))),
      dashboardComponentOrganizations: new FormArray(items.map(item => this.dashboardComponentOrganizationFormService.createDashboardComponentOrganizationFormGroup(item))),
      version: new FormControl(dashboardComponentRawValue.version),
    });
  }

  getDashboardComponent(form: DashboardComponentFormGroup): IDashboardComponent | NewDashboardComponent {
    return form.getRawValue() as IDashboardComponent | NewDashboardComponent;
  }

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

  private getFormDefaults(): DashboardComponentFormDefaults {
    return {
      id: null,
      isExportable: false,
    };
  }
}
