import { ModuleMount } from './mount'
import { ModuleManifest, Application } from '../types'

class ModulePrefetch extends ModuleMount {
  constructor (id: string, model: ModuleManifest, application: Application) {
    super(id, model, application)
  }

  public prefetch () {
    return new Promise((resolve, reject) => {
      Promise.all([
        this.prefetchStatic(this.resources.script, 'script'),
        this.prefetchStatic(this.resources.image, 'image'),
        this.prefetchStatic(this.resources.worker, 'worker'),
        this.prefetchStatic(this.resources.video, 'video'),
        this.prefetchStatic(this.resources.audio, 'audio'),
        this.prefetchStatic(this.resources.font, 'font'),
        this.prefetchStatic(this.resources.style, 'style')
      ]).then(() => {
        this.status.prefetch = true
        resolve(true)
      }).catch(reject)
    })
  }

  public prefetchStatic (list: string[] = [], as = 'script') {
    return new Promise((resolve, reject) => {
      Promise.all([].concat(list as []).map(url => this.beforehandLink(url, 'preload', as))).then(resolve).catch(reject)
    })
  }

  public beforehandLink (url: string, rel: 'prefetch' | 'prerender' | 'preload' = 'preload', as = 'worker | video | audio | font | script | style | image | document'): Promise<Event> {
    if (!url) return Promise.reject()
    return new Promise((resolve, reject) => {
      const link = document.createElement('link')
      link.rel = rel
      link.href = url
      link.as = as
      link.onload = resolve
      link.onerror = reject
      if (!link.relList?.supports(rel)) {
        reject()
      }
      document.getElementsByTagName('head')[0].appendChild(link)
    })
  }
}

export {
  ModulePrefetch
}
