/*! Based On NoSleep.js v0.12.0 - git.io/vfn01 - Rich Tibbett - MIT license */

class PromiseCompleter {
  _promise;
  _resolve;
  _reject;
  constructor() {
    this._promise = new Promise((resolve, reject) => {
      this._resolve = resolve;
      this._reject = reject;
    });
  }

  isCompleted = false;

  get future() {
    return this._promise;
  }

  complete(value) {
    this.isCompleted = true;
    this._resolve(value);
  }

  completeError(error) {
    this._reject(error);
  }
}

var webm =
  'data:video/webm;base64,GkXfo0AgQoaBAUL3gQFC8oEEQvOBCEKCQAR3ZWJtQoeBAkKFgQIYU4BnQI0VSalmQCgq17FAAw9CQE2AQAZ3aGFtbXlXQUAGd2hhbW15RIlACECPQAAAAAAAFlSua0AxrkAu14EBY8WBAZyBACK1nEADdW5khkAFVl9WUDglhohAA1ZQOIOBAeBABrCBCLqBCB9DtnVAIueBAKNAHIEAAIAwAQCdASoIAAgAAUAmJaQAA3AA/vz0AAA='
var mp4 =
  'data:video/mp4;base64, '

var _createClass = (function () {
  function defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i]
      descriptor.enumerable = descriptor.enumerable || false
      descriptor.configurable = true
      if ('value' in descriptor) descriptor.writable = true
      Object.defineProperty(target, descriptor.key, descriptor)
    }
  }
  return function (Constructor, protoProps, staticProps) {
    if (protoProps) defineProperties(Constructor.prototype, protoProps)
    if (staticProps) defineProperties(Constructor, staticProps)
    return Constructor
  }
})()

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError('Cannot call a class as a function')
  }
}

// Detect native Wake Lock API support
var nativeWakeLock = 'wakeLock' in navigator

var NoSleep = (function () {
  var _nativeEnabledCompleter;
  var _playVideoCompleter;

  function NoSleep() {
    var _this = this

    _classCallCheck(this, NoSleep)

    this.nativeEnabled = false
    if (nativeWakeLock) {
      this._wakeLock = null
      var handleVisibilityChange = function handleVisibilityChange() {
        if (_this._wakeLock !== null && document.visibilityState === 'visible') {
          _this.enable()
        }
      }
      document.addEventListener('visibilitychange', handleVisibilityChange)
      document.addEventListener('fullscreenchange', handleVisibilityChange)
    } else {
      // Set up no sleep video element
      this.noSleepVideo = document.createElement('video')

      this.noSleepVideo.setAttribute('title', 'No Sleep')
      this.noSleepVideo.setAttribute('playsinline', '')

      this._addSourceToVideo(this.noSleepVideo, 'webm', webm)
      this._addSourceToVideo(this.noSleepVideo, 'mp4', mp4)

      this.noSleepVideo.addEventListener('loadedmetadata', function () {
        if (_this.noSleepVideo.duration <= 1) {
          // webm source
          _this.noSleepVideo.setAttribute('loop', '')
        } else {
          // mp4 source
          _this.noSleepVideo.addEventListener('timeupdate', function () {
            if (_this.noSleepVideo.currentTime > 0.5) {
              _this.noSleepVideo.currentTime = Math.random()
            }
          })
        }
      })
    }
  }

  _createClass(NoSleep, [
    {
      key: '_addSourceToVideo',
      value: function _addSourceToVideo(element, type, dataURI) {
        var source = document.createElement('source')
        source.src = dataURI
        source.type = 'video/' + type
        element.appendChild(source)
      },
    },
    {
      key: 'enable',
      value: async function enable() {
        var _this2 = this

        if (nativeWakeLock) {
          // Disable any previously held wakelocks.
          await this.disable()
          if (_nativeEnabledCompleter == null) {
            _nativeEnabledCompleter = new PromiseCompleter()
          }
          navigator.wakeLock
            .request('screen')
            .then(function (wakeLock) {
              _this2._wakeLock = wakeLock
              _this2.nativeEnabled = true

              // We now have a wakelock. Notify all of the existing callers.
              _this2._wakeLock.addEventListener('release', function () {
                _this2.nativeEnabled = false
                _this2._wakeLock = null
              })

              _nativeEnabledCompleter.complete()
              _nativeEnabledCompleter = null
            })
            .catch(function (err) {
              _this2.nativeEnabled = false
              var errorMessage = err.name + ', ' + err.message
              _nativeEnabledCompleter.completeError(errorMessage)
              _nativeEnabledCompleter = null
            })
          // We then wait for screen to be made available.
          return _nativeEnabledCompleter.future
        } else {
          if (_playVideoCompleter == null) {
            _playVideoCompleter = new PromiseCompleter()
          }
          var playPromise = this.noSleepVideo.play()
          playPromise.then(function (res) {
            _playVideoCompleter.complete()
            _playVideoCompleter = null
          }).catch(function (err) {
            var errorMessage = err.name + ', ' + err.message
            _playVideoCompleter.completeError(errorMessage)
            _playVideoCompleter = null
          });
          return _playVideoCompleter.future
        }
      },
    },
    {
      key: 'disable',
      value: async function disable() {
        if (nativeWakeLock) {
          // If we're still trying to enable the wakelock, wait for it to be enabled
          if (_nativeEnabledCompleter != null) {
            await _nativeEnabledCompleter.future
          }
          if (this._wakeLock != null) {
            this.nativeEnabled = false
            this._wakeLock.release()
          }

          this._wakeLock = null
        } else {
          if (_playVideoCompleter != null) {
            await _playVideoCompleter.future
          }
          this.noSleepVideo.pause()
        }
        return Promise.resolve();
      },
    },
    {
      key: 'isEnabled',
      value: async function isEnabled() {
        if (nativeWakeLock) {
          // If we're still trying to enable the wakelock, wait for it to be enabled
          if (_nativeEnabledCompleter != null) {
            await _nativeEnabledCompleter.future
          }

          return this.nativeEnabled
        } else {
          if (_playVideoCompleter != null) {
            await _playVideoCompleter.future
          }
          if (this.noSleepVideo == undefined) {
            return false
          }

          return !this.noSleepVideo.paused
        }
      },
    },
  ])

  return NoSleep
})()

var noSleep = new NoSleep()

var Wakelock = {
  enabled: async function () {
    try {
      return noSleep.isEnabled()
    } catch (e) {
      return false
    }
  },
  toggle: async function (enable) {
    try {
      if (enable) {
        await noSleep.enable()
      } else {
        await noSleep.disable()
      }
    } catch (e) {
      return Promise.reject(e);
    }
    return Promise.resolve()
  },
}

if (nativeWakeLock != true) {
  // The first non-native call sometimes throws an error, however,
  // the error does not leak the try-catch above. Therefore, this
  // is an easy fix that realiably works.
  Wakelock.enabled()
}
