import { ChangeDetectorRef, Component, input, OnInit, AfterViewInit, inject, ViewChild, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
import { RouterModule, ActivatedRoute } from '@angular/router';
import { HttpResponse } from '@angular/common/http';
import { map, tap, Observable, EMPTY } from 'rxjs';
import { mergeMap } from 'rxjs/operators';

import SharedModule from 'app/shared/shared.module';
import { IDashboardComponent } from 'app/entities/dashboard-component/dashboard-component.model';
import { IPeriodVersion } from 'app/entities/period-version/period-version.model';
import { PeriodService } from 'app/entities/period/service/period.service';
import { DashboardComponentService, EntityArrayResponseType } from 'app/entities/dashboard-component/service/dashboard-component.service';
import { DashboardComponentFactoryService } from 'app/entities/dashboard-component/factory/dashboard-component-factory.service';
import { IPeriod } from 'app/entities/period/period.model';
import { PeriodSelectorComponent } from 'app/resilient/resilient-environment/period-selector/period-selector.component';

@Component({
  standalone: true,
  selector: 'jhi-dashboard-preview',
  templateUrl: './dashboard-preview.component.html',
  imports: [SharedModule, RouterModule, PeriodSelectorComponent],
})
export class DashboardPreviewComponent implements OnInit, AfterViewInit  {
  @ViewChild('dashboardContainer', { read: ViewContainerRef }) container!: ViewContainerRef;
  
  dashboardComponents?: IDashboardComponent[];
  periodsSharedCollection: IPeriod[] = [];

  dashboardView: string | null = null;
  periodId: number = 0;
  periodVersionId: number | null = null;
  isLoading = false;

  pageTitle: string = '';
  pageSubTitle: string = '';
  showComponentTitle: boolean = false;

  protected dashboardComponentService = inject(DashboardComponentService);
  protected periodService = inject(PeriodService);
  
  constructor(
    private dashboardComponentFactory: DashboardComponentFactoryService,
    private cdRef: ChangeDetectorRef, // Inject ChangeDetectorRef
    private route: ActivatedRoute
  ) {}
  
  
  comparePeriod = (o1: IPeriod | null, o2: IPeriod | null): boolean =>
    this.periodService.compareEntity(o1, o2);

  ngOnInit(): void {
    this.isLoading = true;
    
    this.route.paramMap.subscribe(params => {
      this.dashboardView = params.get('view') ?? null;
      
      // used the operator (+) that auto-casts a string to a number
      this.periodId = +(params.get('period') ?? 0);
      
      // periodVersion might not be defined. In this case, it will calculate the most recent version
      if (params.get('period_version') != null) {
        this.periodVersionId = +(params.get('period_version')!);
      }
      
      // Page titles
      this.setPageTitles(this.dashboardView);
      
      // Force build
      this.build();
    });
    
    // Get the latest PeriodVersion for the requested Period
    if (this.periodVersionId == null) {
      this.periodService
        .lastVersion(this.periodId)
        .subscribe({
          next: (version: HttpResponse<IPeriodVersion>) => {
            if (version.body) {
              const periodVersion = version.body;
              this.periodVersionId = periodVersion.id;
            } else {
              this.periodVersionId = null;
            }
            
            //Fire Loading of the dashboard
            this.build();
          },
        });
    } else {
      //Fire Loading of the dashboard
      this.build();
    }
    
    this.loadRelationshipsOptions();
  }
  
  onSearch(): void {
	  this.build();
  }
  
  ngAfterViewInit() {
    this.loadDashboards();
  }
  
  build(): void {
    if (this.periodVersionId == null) {
      // Can't load dashboard without a version
      this.dashboardComponents = [];  // Clear components
      return;
    }
    
    // Load a list of dashboarComponent's to render
    this.loadDashboards().subscribe({
      next: (res: EntityArrayResponseType) => {
        this.dashboardComponents = res.body ?? [];
        
        this.container.clear();
        
        this.dashboardComponents.forEach((dashComp, index) => {
          this.loadDashboard(dashComp, this.periodVersionId!);
        });
      },
    });
  }
  
  loadDashboard(_dashboardComponent: IDashboardComponent, periodVersionId: number): void {

    if (_dashboardComponent?.type) {      
      const data = { dashboardComponent: _dashboardComponent, periodVersionId: this.periodVersionId, showTitle: this.showComponentTitle };
      this.dashboardComponentFactory.createComponent(_dashboardComponent?.type, this.container, data);
      
      // **Force Angular to detect changes**
      this.cdRef.detectChanges();
    }
  }
  
  protected loadDashboards(): Observable<EntityArrayResponseType> {
    if (this.dashboardView) {
      return this.dashboardComponentService.getAllActiveForView(this.dashboardView).pipe(tap(() => (this.isLoading = false)));
    } else {
      return EMPTY;
    }
  }
  
  protected loadRelationshipsOptions(): void {
    this.periodService
      .query()
      .pipe(map((res: HttpResponse<IPeriod[]>) => res.body ?? []))
      .subscribe((periods: IPeriod[]) => { 
        this.periodsSharedCollection = periods;
      });
  }  
  
  protected setPageTitles(view: string | null): void {
    this.pageTitle = '';
    this.pageSubTitle = '';
    
    if (view) {
      if (view==='EMISSIONS') {
        this.pageTitle = 'Emissões de Gases com Efeito de Estufa';
        this.pageSubTitle = 't CO<sub>2</sub>e';
        this.showComponentTitle = false;
      } else if (view==='INDICATORS') {
        this.pageTitle = 'Indicadores';
        this.pageSubTitle = '';
        this.showComponentTitle = true;
      }
    }
  }
}
