import { toQuery } from '../../utils/url'

class PopupWindowRyeShopifyAuth {
  id: any
  url: any
  options: any
  resolver: () => Promise<boolean>

  window: Window | null | undefined
  promise: Promise<unknown> | undefined
  private _iid: number | undefined | null

  constructor(
    id: string,
    url: string,
    options = {},
    resolver: () => Promise<boolean>
  ) {
    this.id = id
    this.url = url
    this.options = options
    this.resolver = resolver
  }

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

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

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

  poll() {
    this.promise = new Promise((resolve, reject) => {
      this._iid = window.setInterval(async () => {
        try {
          const popup = this.window
          if (!popup || popup.closed !== false) {
            this.close()
            reject(new Error('The popup was closed'))
            return
          }

          if (await this.resolver()) {
            resolve({})
            this.close()
          }
        } catch (error) {
          /*
           * Ignore DOMException: Blocked a frame with origin from accessing a
           * cross-origin frame.
           */
          console.log('Ignore error', error)
        }
      }, 1000)
    })
  }

  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,
    resolver: () => Promise<boolean>
  ) {
    const popup = new this(id, url, options, resolver)

    popup.open()
    popup.poll()

    return popup
  }
}

export default PopupWindowRyeShopifyAuth
