import { Component, inject, OnInit } from '@angular/core';
import { HttpResponse } from '@angular/common/http';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { finalize, map } from 'rxjs/operators';

import SharedModule from 'app/shared/shared.module';
import { FormsModule, ReactiveFormsModule, FormArray } from '@angular/forms';
import { DragDropModule, CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { ColorPickerModule } from 'ngx-color-picker';
import { NgSelectModule } from '@ng-select/ng-select';

import { IDashboardComponent, NewDashboardComponent } from '../dashboard-component.model';
import { DashboardComponentType } from 'app/entities/enumerations/dashboard-component-type.model';
import { DashboardComponentView } from 'app/entities/enumerations/dashboard-component-view.model';
import { DashboardComponentChartType } from 'app/entities/enumerations/dashboard-component-chart-type.model';
import { DashboardComponentService } from '../service/dashboard-component.service';
import { DashboardComponentFormService, DashboardComponentFormGroup } from './dashboard-component-form.service';
import { DashboardComponentDetailFormService } from './dashboard-component-detail-form.service';
import { IVariable } from 'app/entities/variable/variable.model';
import { VariableService } from 'app/entities/variable/service/variable.service';
import { AbstractResilientEntityComponent } from 'app/entities/resilient/resilient-entity.component';
import { DashboardComponentOrganizationFormService } from './dashboard-component-organization-form.service';
import { OrganizationService } from 'app/entities/organization/service/organization.service';
import { IOrganization } from 'app/entities/organization/organization.model';
import { OrganizationNature } from 'app/entities/enumerations/organization-nature.model';

@Component({
  standalone: true,
  selector: 'jhi-dashboard-component-update',
  templateUrl: './dashboard-component-update.component.html',
  imports: [SharedModule, ColorPickerModule, DragDropModule, FormsModule, ReactiveFormsModule, NgSelectModule],
})
export class DashboardComponentUpdateComponent extends AbstractResilientEntityComponent<IDashboardComponent, NewDashboardComponent, DashboardComponentService> implements OnInit {
  isSaving = false;
  dashboardComponent: IDashboardComponent | null = null;
  currentTab: string = 'details'; // default tab
  dashboardComponentTypes = Object.keys(DashboardComponentType);
  dashboardComponentViews = Object.keys(DashboardComponentView);
  dashboardComponentChartTypes = Object.keys(DashboardComponentChartType);
  
  outputVariablesSharedCollection: IVariable[] = [];
  organizationsSharedCollection: IOrganization[] = [];
  dashboardComponentSharedCollection: IDashboardComponent[] = [];
  
  protected variableService = inject(VariableService);
  protected organizationService = inject(OrganizationService);
  protected dashboardComponentService = inject(DashboardComponentService);
  protected dashboardComponentFormService = inject(DashboardComponentFormService);
  protected dashboardComponentDetailFormService = inject(DashboardComponentDetailFormService);
  protected dashboardComponentOrganizationFormService = inject(DashboardComponentOrganizationFormService);
  protected activatedRoute = inject(ActivatedRoute);

  compareOutputVariable = (o1: IVariable | null, o2: IVariable | null): boolean => this.variableService.compareEntity(o1, o2);
  compareOrganization = (o1: IOrganization | null, o2: IOrganization | null): boolean => this.organizationService.compareEntity(o1, o2);
  compareDashboardComponent = (o1: IDashboardComponent | null, o2: IDashboardComponent | null): boolean => this.dashboardComponentService.compareEntity(o1, o2);

  // eslint-disable-next-line @typescript-eslint/member-ordering
  editForm: DashboardComponentFormGroup = this.dashboardComponentFormService.createDashboardComponentFormGroup();

  constructor(service: DashboardComponentService) { super(service); }

  ngOnInit(): void {
    this.activatedRoute.data.subscribe(({ dashboardComponent }) => {
      this.dashboardComponent = dashboardComponent;
      if (dashboardComponent) {
        this.updateForm(dashboardComponent);
      }
      
      this.loadRelationshipsOptions();
    });
  }

  previousState(): void {
    window.history.back();
  }

  save(): void {
    this.isSaving = true;
    const dashboardComponent = this.dashboardComponentFormService.getDashboardComponent(this.editForm);
    if (dashboardComponent.id !== null) {
      this.subscribeToSaveResponse(this.dashboardComponentService.update(dashboardComponent));
    } else {
      this.subscribeToSaveResponse(this.dashboardComponentService.create(dashboardComponent));
    }
  }

  setTab(tabId: string): void {
    this.currentTab = tabId;
  }
  
  /* Nested collection methods : DashboardComponentDetail's  */
  /* Use it like a property : this.dashboardComponentDetails */
  get dashboardComponentDetails(): FormArray {
    return this.editForm.get('dashboardComponentDetails') as FormArray;
  }
  
  addDashboardComponentDetail(): void {
    // Calculate the indexOrder for the new DashboardComponentDetail
    const maxIdx = this.dashboardComponentDetails.length ?? 0;
    const newDashboardComponentDetail = this.dashboardComponentDetailFormService.createDashboardComponentDetailFormGroup();
    newDashboardComponentDetail.patchValue({indexOrder: maxIdx+1});
    
    // Add to the formarray
    this.dashboardComponentDetails.push( newDashboardComponentDetail );
  }

  removeDashboardComponentDetail(index: number): void {
    this.dashboardComponentDetails.removeAt(index);
  }

 /* Nested collection methods : DashboardComponentOrganization's  */
  /* Use it like a property : this.dashboardComponentOrganizations */
  get dashboardComponentOrganizations(): FormArray {
    return this.editForm.get('dashboardComponentOrganizations') as FormArray;
  }

  addDashboardComponentOrganization(): void {
    // Calculate the indexOrder for the new DashboardComponentOrganization
    const maxIdx = this.dashboardComponentOrganizations.length ?? 0;
    const newDashboardComponentOrganization = this.dashboardComponentOrganizationFormService.createDashboardComponentOrganizationFormGroup();

    // Add to the formarray
    this.dashboardComponentOrganizations.push( newDashboardComponentOrganization );
  }

  removeDashboardComponentOrganization(index: number): void {
    this.dashboardComponentOrganizations.removeAt(index);
  }

  protected subscribeToSaveResponse(result: Observable<HttpResponse<IDashboardComponent>>): void {
    result.pipe(finalize(() => this.onSaveFinalize())).subscribe({
      next: () => this.onSaveSuccess(),
      error: () => this.onSaveError(),
    });
  }

  protected onSaveSuccess(): void {
    this.previousState();
  }

  protected onSaveError(): void {
    // Api for inheritance.
  }

  protected onSaveFinalize(): void {
    this.isSaving = false;
  }

  protected updateForm(dashboardComponent: IDashboardComponent): void {
    this.dashboardComponent = dashboardComponent;
    this.dashboardComponentFormService.resetForm(this.editForm, dashboardComponent);
	
    // dashboardComponent.dashboardComponentDetails FormArray
    dashboardComponent.dashboardComponentDetails?.forEach(dashCompDetail => {
      this.dashboardComponentDetails.push(this.dashboardComponentDetailFormService.createDashboardComponentDetailFormGroup(dashCompDetail));
    });

    // dashboardComponent.dashboardComponentOrganizations FormArray
    dashboardComponent.dashboardComponentOrganizations?.forEach(dashCompOrg => {
      this.dashboardComponentOrganizations.push(this.dashboardComponentOrganizationFormService.createDashboardComponentOrganizationFormGroup(dashCompOrg));
    });
  }
  
  protected loadRelationshipsOptions(): void {
    const queryObject: any = {
      eagerload: true,
      //sort: this.sortService.buildSortParam(this.sortState()),
    };
    var clause: string = "equals";
    var key: string = "output"; 
    var value: string = "true"; 
    queryObject[key + "." + clause] = value;
    this.variableService
      .query(queryObject)
      .pipe(map((res: HttpResponse<IVariable[]>) => res.body ?? []))
      .subscribe((outputVariables: IVariable[]) => (this.outputVariablesSharedCollection = outputVariables));
      
    var clause: string = "equals";
    var key: string = "type"; 
    var value: string = this.dashboardComponent?.type ?? ""; 
    queryObject[key + "." + clause] = value;
    this.dashboardComponentService
      .query(queryObject)
      .pipe(map((res: HttpResponse<IDashboardComponent[]>) => res.body ?? []))
      .subscribe((dashboardComponents: IDashboardComponent[]) => (this.dashboardComponentSharedCollection = dashboardComponents));

    this.organizationService
      .queryByNature(OrganizationNature.ORGANIZATION)
      .pipe(map((res: HttpResponse<IOrganization[]>) => res.body ?? []))
      .subscribe((organizations: IOrganization[]) => (this.organizationsSharedCollection = organizations));
      
  }
  
  drop(event: CdkDragDrop<any[]>): void {
    if (this.dashboardComponentDetails) {
      // Save the original indexOrder values
      const idx_1 = this.dashboardComponentDetails.at(event.previousIndex).value.indexOrder;
      const idx_2 = this.dashboardComponentDetails.at(event.currentIndex).value.indexOrder;

      // Switch the indexOrder
      this.dashboardComponentDetails?.at(event.previousIndex).patchValue({ indexOrder: idx_2 });
      this.dashboardComponentDetails?.at(event.currentIndex).patchValue({ indexOrder: idx_1 });
      
      // Switch the values within the FormArray, to visually move the row
      moveItemInArray(this.dashboardComponentDetails.controls, event.previousIndex, event.currentIndex);
    } else {
      // NEVER happens. To call drop(), the dashboardComponentDetails collections must have values
      console.warn('dashboardComponent or dashboardComponentDetails is undefined');
    }
  }
  
  variableSearchFn = (term: string, item: any) => {
    term = term.toLowerCase();
    return (item.code + ' ' + item.name).toLowerCase().includes(term);
  };

}
