import { Injectable } from '@angular/core'
import { Observable, forkJoin, BehaviorSubject, of } from 'rxjs'
import { map } from 'rxjs/operators'

import { StyleSpecification } from 'maplibre-gl'

import { MapControlService } from './map-control.service'
import { MapService, MapInitData, BaseMapWithStores, BaseStyle as OApiBaseStyle } from '../openapi'

export class BaseStyle {
  constructor(
    public name: string,
    public style?: StyleSpecification,
  ) { }
}

@Injectable()
export class MapDataService {
  constructor(
    // private apollo: Apollo,
    protected mapControlService: MapControlService,
    public mapService: MapService,
  ) {
    // Get the data on init, as it is (most probably) immutable
    this.getMapInitData().subscribe(
      data => {
        this.mapInitDataLoaded.next(true)
        this.mapInitDataLoaded.complete()
      }
    )
  }

  public mapInitDataLoaded = new BehaviorSubject<boolean>(false)
  mapInitDataLoaded$ = this.mapInitDataLoaded.asObservable()

  mapInitData: MapInitData = {}

  getMapInitData(): Observable<MapInitData> {
    return this.mapService.getInitDataApiMapInitDataGet().pipe(map(
      data => this.mapInitData = data
    ))
  }

  // getBaseMaps(): Observable<BaseMap[]> {
  //     return this.apollo.query({
  //         query: baseMapQuery,
  //     }).pipe(map(
  //         res => {
  //             let bms: object = res['data']['baseMap']
  //             return bms['map'](
  //                 (bm: object) => new BaseMap(
  //                     bm['name'],
  //                     bm['stores'].map(
  //                         (store: object) => new Store(store['name'])
  //                     )
  //                 )
  //             )
  //         }
  //     ))
  // }

  public createBaseMap(baseMapName: string, stores: string[]): Observable<BaseMapWithStores> {
    console.log('TODO: Migrate Graphql createBaseMap')
    return of({ name: '', stores: [] })
    // return this.apollo.mutate({
    //     mutation: createBaseMapQuery,
    //     variables: {
    //         baseMapName: baseMapName,
    //         stores: stores
    //     }
    // }).pipe(map(
    //     res => {
    //         let bm: object = res['data']['createBaseMap']['baseMap']
    //         return new BaseMap(
    //             bm['name'],
    //             bm['stores'].map((store: object) => new Store(store['name']))
    //         )
    //     }
    // ))
  }

  // XXX: unused
  // getBaseStyleList(): Observable<BaseStyle[]> {
  //     return this.apollo.query({query: baseStyleListQuery}).pipe(map(
  //         data => data['data']['base_style_list'].map(
  //             (baseStyle: string) => new BaseStyle(baseStyle['name'])
  //         )
  //     ))
  // }

  getBaseStyle(styleName: string): Observable<BaseStyle> {
    return this.mapService.getBaseStyleApiMapBaseStyleNameGet({ name: styleName }).pipe(map(
      (data: OApiBaseStyle) => new BaseStyle(data.name, <any>data.style)
    ))
  }

  // getStores(): Observable<LayerNode[]> {
  //     return this.apollo.query({
  //         query: storeQuery,
  //     }).pipe(map(
  //         res => res['data']['stores'].map(
  //             (layer: Object) => new LayerNode(
  //                 layer['name'],
  //                 layer['group'],
  //                 layer['icon'],
  //                 layer['symbol'] || gisTypeSymbolMap[layer['gisType']],
  //                 layer['store'],
  //                 layer['rawSurveyStore'],
  //                 layer['type'],
  //                 layer['gisType'],
  //                 layer['style'],
  //                 layer['zIndex'],
  //                 layer['count'],
  //                 layer['description'],
  //                 layer['live'],
  //                 layer['custom'],
  //                 layer['tagPlugins'],
  //                 layer['viewableRole']
  //             )
  //         )
  //     ))
  // }

  // getPrimaryGroups(): Observable<PrimaryGroupNode[]> {
  //     return this.apollo.query({
  //         query: geomGroupQuery,
  //     }).pipe(map(
  //         res => res['data']['geomGroup'] && res['data']['geomGroup'].map(
  //             (gg: Object) => new PrimaryGroupNode(
  //                 gg['name'],
  //                 gg['title'],
  //                 gg['description']
  //             )
  //         )
  //     ))
  // }
}
