import qs from 'query-string'
import { toQuery } from '../../utils/url'

class PopupWindowSpotifyAuth {
  id: any
  url: any
  options: any
  window: Window | null | undefined
  promise: Promise<unknown> | undefined
  private _iid: number | undefined | null
  constructor(id: string, url: string, options = {}) {
    this.id = id
    this.url = url
    this.options = options
  }

  open() {
    const { url, id, options } = this
    this.window = window.open(url, id, toQuery(options, ','))
  }

  navigate(url: string) {
    if (this.window) {
      this.window.location.href = url
    }
  }

  close() {
    this.cancel()
    this.window?.close()
  }

  poll() {
    this.promise = new Promise((resolve, reject) => {
      this._iid = window.setInterval(() => {
        try {
          const popup = this.window

          if (!popup || popup.closed !== false) {
            this.close()
            reject(new Error('The popup was closed'))
            return
          }

          if (
            popup.location.href === this.url ||
            popup.location.pathname === 'blank'
          ) {
            return
          }

          const { query } = qs.parseUrl(popup.location.search)

          if ('access_token' in query && 'refresh_token' in query) {
            resolve(query)
            this.close()
          }
        } catch (error) {
          /*
           * Ignore DOMException: Blocked a frame with origin from accessing a
           * cross-origin frame.
           */
        }
      }, 500)
    })
  }

  cancel() {
    if (this._iid) {
      window.clearInterval(this._iid)
      this._iid = null
    }
  }

  then(...args: any[]) {
    return this.promise?.then(...args)
  }

  catch(...args: any[]) {
    return this.promise?.then(...args)
  }

  static open(id: string, url: string, options: any) {
    const popup = new this(id, url, options)

    popup.open()
    popup.poll()

    return popup
  }
}

export default PopupWindowSpotifyAuth
