import { Component, NgZone, inject, OnInit } from '@angular/core';
import { ActivatedRoute, Data, ParamMap, Router, RouterModule } from '@angular/router';
import { combineLatest, filter, Observable, Subscription, tap, map } from 'rxjs';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { HttpResponse } from '@angular/common/http';


import SharedModule from 'app/shared/shared.module';
import { sortStateSignal, SortDirective, SortByDirective, type SortState, SortService } from 'app/shared/sort';
import { DurationPipe, FormatMediumDatetimePipe, FormatMediumDatePipe } from 'app/shared/date';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { SORT, ITEM_DELETED_EVENT, DEFAULT_SORT_DATA } from 'app/config/navigation.constants';
import { IEmissionFactor } from '../emission-factor.model';
import { EntityArrayResponseType, EmissionFactorService } from '../service/emission-factor.service';
import { EmissionFactorDeleteDialogComponent } from '../delete/emission-factor-delete-dialog.component';

import { EmissionFactorSearchFormService, EmissionFactorSearchFormGroup } from './emission-factor-search-form.service';
import { IVariableScope } from 'app/entities/variable-scope/variable-scope.model';
import { VariableScopeService } from 'app/entities/variable-scope/service/variable-scope.service';
import { IVariableCategory } from 'app/entities/variable-category/variable-category.model';
import { VariableCategoryService } from 'app/entities/variable-category/service/variable-category.service';


@Component({
  standalone: true,
  selector: 'jhi-emission-factor',
  templateUrl: './emission-factor.component.html',
  imports: [
    RouterModule,
    FormsModule,
    ReactiveFormsModule,
    SharedModule,
    SortDirective,
    SortByDirective,
    DurationPipe,
    FormatMediumDatetimePipe,
    FormatMediumDatePipe,
  ],
})
export class EmissionFactorComponent implements OnInit {
  subscription: Subscription | null = null;
  emissionFactors?: IEmissionFactor[];
  isLoading = false;

  sortState = sortStateSignal({});
  
  variableScopesSharedCollection: IVariableScope[] = [];
  variableCategoriesSharedCollection: IVariableCategory[] = [];

  public router = inject(Router);
  protected variableScopeService = inject(VariableScopeService);
  protected variableCategoryService = inject(VariableCategoryService);
  protected emissionFactorService = inject(EmissionFactorService);
  protected emissionFactorSearchFormService = inject(EmissionFactorSearchFormService);
  protected activatedRoute = inject(ActivatedRoute);
  protected sortService = inject(SortService);
  protected modalService = inject(NgbModal);
  protected ngZone = inject(NgZone);

  searchForm: EmissionFactorSearchFormGroup = this.emissionFactorSearchFormService.createEmissionFactorSearchFormGroup();
  trackId = (_index: number, item: IEmissionFactor): number => this.emissionFactorService.getEntityIdentifier(item);

  compareVariableScope = (o1: IVariableScope | null, o2: IVariableScope | null): boolean =>
    this.variableScopeService.compareEntity(o1, o2);

  compareVariableCategory = (o1: IVariableCategory | null, o2: IVariableCategory | null): boolean =>
    this.variableCategoryService.compareEntity(o1, o2);

  ngOnInit(): void {
    this.subscription = combineLatest([this.activatedRoute.queryParamMap, this.activatedRoute.data])
      .pipe(
        tap(([params, data]) => this.fillComponentAttributeFromRoute(params, data)),
        tap(() => {
          if (!this.emissionFactors || this.emissionFactors.length === 0) {
            this.load();
          }
        }),
      )
      .subscribe();
      
    // Listen to changes to the scope filter property
    this.searchForm.get('variableScopeId')?.valueChanges.subscribe((scopeId) => {
      this.loadCategoriesOfSelectedScope(scopeId);
      this.searchForm.get('variableCategoryId')?.setValue(null);
    });
    
    this.loadRelationshipsOptions();
  }

  delete(emissionFactor: IEmissionFactor): void {
    const modalRef = this.modalService.open(EmissionFactorDeleteDialogComponent, { size: 'lg', backdrop: 'static' });
    modalRef.componentInstance.emissionFactor = emissionFactor;
    // unsubscribe not needed because closed completes on modal close
    modalRef.closed
      .pipe(
        filter(reason => reason === ITEM_DELETED_EVENT),
        tap(() => this.load()),
      )
      .subscribe();
  }

  onSearch(): void {
	  this.load();
  }
  
  
  load(): void {
    this.queryBackend().subscribe({
      next: (res: EntityArrayResponseType) => {
        this.onResponseSuccess(res);
      },
    });
  }

  navigateToWithComponentValues(event: SortState): void {
    this.handleNavigation(event);
  }

  protected fillComponentAttributeFromRoute(params: ParamMap, data: Data): void {
    this.sortState.set(this.sortService.parseSortParam(params.get(SORT) ?? data[DEFAULT_SORT_DATA]));
  }

  protected onResponseSuccess(response: EntityArrayResponseType): void {
    const dataFromBody = this.fillComponentAttributesFromResponseBody(response.body);
    this.emissionFactors = this.refineData(dataFromBody);
  }

  protected refineData(data: IEmissionFactor[]): IEmissionFactor[] {
    const { predicate, order } = this.sortState();
    return predicate && order ? data.sort(this.sortService.startSort({ predicate, order })) : data;
  }

  protected fillComponentAttributesFromResponseBody(data: IEmissionFactor[] | null): IEmissionFactor[] {
    return data ?? [];
  }

  protected queryBackend(): Observable<EntityArrayResponseType> {
    this.isLoading = true;
    const queryObject: any = {
      eagerload: true,
      sort: this.sortService.buildSortParam(this.sortState()),
    };
    
    const searchModel = this.emissionFactorSearchFormService.getEmissionFactor(this.searchForm);
    this.emissionFactorSearchFormService.applySearchConditionsToQueryObject(queryObject, searchModel);
	
    return this.emissionFactorService.queryByCriteria(queryObject).pipe(tap(() => (this.isLoading = false)));
  }

  protected handleNavigation(sortState: SortState): void {
    const queryParamsObj = {
      sort: this.sortService.buildSortParam(sortState),
    };

    this.ngZone.run(() => {
      this.router.navigate(['./'], {
        relativeTo: this.activatedRoute,
        queryParams: queryParamsObj,
      });
    });
  }
  
  protected loadCategoriesOfSelectedScope(scopeId: number|null|undefined): void {
    if (scopeId) {
      this.variableCategoryService
          .queryByScopeForFactor(scopeId)
          .pipe(map((res: HttpResponse<IVariableCategory[]>) => res.body ?? []))
          .subscribe((cats: IVariableCategory[]) => (this.variableCategoriesSharedCollection = cats));
    } else {
      this.variableCategoriesSharedCollection = [];
    }
  }
  
  protected loadRelationshipsOptions(): void {
    this.variableScopeService
      .query()
      .pipe(map((res: HttpResponse<IVariableScope[]>) => res.body ?? []))
      .subscribe((variableScopes: IVariableScope[]) => (this.variableScopesSharedCollection = variableScopes));
  }  
}
