import { AfterViewInit, Directive, Input, OnDestroy, OnInit, Optional } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { OpenLayersLayerFactory, OpenLayersMapComponent } from '../../generic-maps';
import { LocationLayer } from '../model';
import { LocationRendererDirective } from './location-renderer.directive';
import { LocationStyleService } from './location-style.service';
import { LocationMapService } from './location-map.service';
import { takeUntil } from 'rxjs/operators';
import VectorSource from 'ol/source/Vector';
import TileLayer from 'ol/layer/Tile';

@Directive({
  selector: '[bciLocationLayer]',
})
export class LocationLayerDirective implements OnInit, AfterViewInit, OnDestroy {
  @Input() customeBaseLayer: TileLayer;
  @Input() locationLayers: Observable<LocationLayer[]>;

  protected locationVectorSources: VectorSource[] = [];
  protected ngUnsubscribe = new Subject<void>();

  constructor(
    protected mapComponent: OpenLayersMapComponent,
    protected openLayersLayerFactory: OpenLayersLayerFactory,
    protected locationMapService: LocationMapService,
    protected locationStyleService: LocationStyleService,
    @Optional() protected renderer: LocationRendererDirective
  ) {}

  ngOnInit(): void {
    if (!this.locationLayers) {
      this.locationLayers = this.locationMapService.locationLayers;
    }
  }

  ngAfterViewInit(): void {
    this.initMapLayers();
    this.addLocationLayers();
  }

  ngOnDestroy(): void {
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
  }

  initMapLayers(): void {
    // Adding base tile layer
    if (this.customeBaseLayer) {
      this.mapComponent.addLayer(this.customeBaseLayer);
    } else {
      this.mapComponent.addOSM(1, 0.25);
    }
  }

  addLocationLayers(): void {
    this.locationLayers.pipe(takeUntil(this.ngUnsubscribe)).subscribe((layers: LocationLayer[]) => {
      // Adding feature layers
      layers.forEach((layer: LocationLayer, index: number) => {
        this.locationVectorSources[index] = this.openLayersLayerFactory.createVectorSource();
        this.mapComponent.addLayer(
          this.openLayersLayerFactory.createVectorLayer(this.locationVectorSources[index], 10 * (index + 1), <any>{
            style: this.locationStyleService.locationStyleDefault,
            declutter: false,
            ...(layer.options || {}),
          })
        );
      });

      // Rendering layers
      layers.forEach((layer, index) => {
        if (!!this.renderer) {
          this.renderer.render(this.locationVectorSources[index], layer.locations);
          this.renderer.updateStyles([]);
        }
      });
    });
  }
}
