declare const SMap: any
declare const Plugins: any

export interface ConfigProp {
  el: string
  options: MapOptionsProp
  sources: string[]
}

export interface MapOptionsProp {
  viewMode?: string
  center?: number[]
  zooms?: number[]
  zoom?: number
  pitch?: number
  mapStyle?: string
  showBuildingBlock?: boolean
}

class Map {
  map: any
  config: ConfigProp
  constructor(config: ConfigProp) {
    this.config = config
  }
  injectSource(): Promise<unknown[]> {
    const promises = this.config.sources.map(
      (source: string, index: number) => {
        return new Promise((resolve) => {
          if (document.getElementById(`_source${index}`)) {
            resolve(true)
            return
          }
          const sourceJs = document.createElement('script')
          sourceJs.type = 'text/javascript'
          sourceJs.src = source
          sourceJs.setAttribute('id', `_source${index}`)
          document.head.appendChild(sourceJs)
          window.onload = () => resolve(true)
        })
      }
    )
    return Promise.all(promises)
  }
}

export class S_Map extends Map {
  constructor(config: ConfigProp) {
    super(config)
    this.injectSource().then(this.initMap)
  }
  initMap(): void {
    this.map = new SMap.Map(this.config.el, this.config.options)
  }
  onLoaded(cb: (arg: unknown) => void): void {
    this.map.on(SMap.MapEvent.maploaded, cb)
  }
  onZoomChange(cb: (arg: unknown) => void): void {
    this.map.on(SMap.MapEvent.zoomchanged, cb)
  }
  onCenterChange(cb: (arg: unknown) => void): void {
    this.map.on(SMap.MapEvent.centerchanged, cb)
  }
  onBlur(cb: (arg: unknown) => void): void {
    this.map.on(SMap.MapEvent.blur, cb)
  }
  onFocus(cb: (arg: unknown) => void): void {
    this.map.on(SMap.MapEvent.focus, cb)
  }
  onDrag(cb: (arg: unknown) => void): void {
    this.map.on(SMap.MapEvent.drag, cb)
  }
  onClick(cb: (arg: unknown, point: unknown) => void): void {
    this.map.on(SMap.MapEvent.click, (view: any, eventParamter: any) => {
      view.hitTest(eventParamter).then((res: any) => {
        if (res.results && res.results.length > 0) {
          cb(
            res.results[0] && res.results[0].graphic.attributes,
            eventParamter.mapPoint
          )
        }
      })
    })
  }
}
