import {Pipe, PipeTransform} from '@angular/core';
import {MapService} from '@maplibre/ngx-maplibre-gl';
import {Feature, Point} from 'geojson';
import {MapGeoJSONFeature, type GeoJSONSource} from 'maplibre-gl';
import {combineLatest, distinctUntilChanged, map, mergeMap, from, Observable, ReplaySubject} from 'rxjs';
import {SCFeatureProperties} from './feature-collection.pipe';

@Pipe({
  name: 'mglClusterLeaves',
  standalone: true,
  pure: true,
})
export class MglClusterLeavesPipe implements PipeTransform {
  source = new ReplaySubject<string>(1);

  feature = new ReplaySubject<MapGeoJSONFeature>(1);

  limit = new ReplaySubject<number>(1);

  offset = new ReplaySubject<number>(1);

  leaves: Observable<Feature<Point, SCFeatureProperties>[]> = combineLatest([
    this.source.pipe(
      distinctUntilChanged(),
      map(source => this.mapService.getSource(source) as GeoJSONSource),
    ),
    this.feature.pipe(distinctUntilChanged(it => it.properties.cluster_id)),
    this.limit.pipe(distinctUntilChanged()),
    this.offset.pipe(distinctUntilChanged()),
  ]).pipe(
    mergeMap(([source, feature, limit, offset]) =>
      from(source.getClusterLeaves(feature.properties.cluster_id, limit, offset)),
    ),
  );

  constructor(private mapService: MapService) {}

  transform(
    source: string,
    feature: MapGeoJSONFeature,
    limit = 0,
    offset = 0,
  ): Observable<Feature<Point, SCFeatureProperties>[]> {
    // MapLibre triggers change detection when the map moves, so this is to prevent flicker
    this.source.next(source);
    this.feature.next(feature);
    this.limit.next(limit);
    this.offset.next(offset);
    return this.leaves;
  }
}
