/* eslint-disable no-param-reassign */
/* eslint-disable func-names */
/* eslint-disable no-undef */
/* eslint-disable max-classes-per-file */
/**
 * Constants of states for media playback
 * @enum {string}
 */
const PLAYER_STATE = {
  ERROR: 'ERROR',
  IDLE: 'IDLE',
  LOADED: 'LOADED',
  LOADING: 'LOADING',
  PAUSED: 'PAUSED',
  PLAYING: 'PLAYING',
  STOPPED: 'STOPPED',
}

/**
 * Cast player object
 * Main variables:
 *  - PlayerHandler object for handling media playback
 *  - Cast player variables for controlling Cast mode media playback
 *  - Current media variables for transition between Cast and local modes
 * @struct @constructor
 */
export class CastPlayer {
  constructor(source, teamsInfo) {
    /** @type {PlayerHandler} Delegation proxy for media playback */
    this.playerHandler = new PlayerHandler(this)

    /** @type {PLAYER_STATE} A state for media playback */
    this.playerState = PLAYER_STATE.IDLE

    /* Cast player variables */
    /** @type {cast.framework.RemotePlayer} */
    this.remotePlayer = null
    /** @type {cast.framework.RemotePlayerController} */
    this.remotePlayerController = null

    this.src = source
    this.teamsInfo = teamsInfo
  }

  initializeCastPlayer() {
    const options = {}

    // Set the receiver application ID to your own (created in the
    // Google Cast Developer Console), or optionally
    // use the chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID
    options.receiverApplicationId = chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID

    // Auto join policy can be one of the following three:
    // ORIGIN_SCOPED - Auto connect from same appId and page origin
    // TAB_AND_ORIGIN_SCOPED - Auto connect from same appId, page origin, and tab
    // PAGE_SCOPED - No auto connect
    options.autoJoinPolicy = chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED
    options.androidReceiverCompatible = false

    cast.framework.CastContext.getInstance().setOptions(options)

    // const credentialsData = new chrome.cast.CredentialsData('{"userId": "abc"}')
    // cast.framework.CastContext.getInstance().setLaunchCredentialsData(credentialsData)

    this.remotePlayer = new cast.framework.RemotePlayer()
    this.remotePlayerController = new cast.framework.RemotePlayerController(this.remotePlayer)
    this.remotePlayerController.addEventListener(
      cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED,
      this.switchPlayer.bind(this),
    )
  }

  /*
   * PlayerHandler and setup functions
   */
  switchPlayer() {
    this.playerState = PLAYER_STATE.IDLE
    if (cast && cast.framework && this.remotePlayer.isConnected) {
      this.setupRemotePlayer()
    }
  }

  /**
   * Set the PlayerHandler target to use the remote player
   */
  setupRemotePlayer() {
    const castSession = cast.framework.CastContext.getInstance().getCurrentSession()

    // This object will implement PlayerHandler callbacks with
    // remotePlayerController, and makes necessary UI updates specific
    // to remote playback
    const playerTarget = {}

    playerTarget.play = function () {
      if (this.remotePlayer.isPaused) {
        this.remotePlayerController.playOrPause()
      }
    }.bind(this)

    playerTarget.pause = function () {
      if (!this.remotePlayer.isPaused) {
        this.remotePlayerController.playOrPause()
      }
    }.bind(this)

    playerTarget.stop = function () {
      this.remotePlayerController.stop()
    }.bind(this)

    playerTarget.load = function () {
      const mediaInfo = new chrome.cast.media.MediaInfo(this.src, 'video/mp4')

      mediaInfo.metadata = new chrome.cast.media.GenericMediaMetadata()
      mediaInfo.metadata.metadataType = chrome.cast.media.MetadataType.GENERIC
      mediaInfo.metadata.title = this.teamsInfo
      // mediaInfo.metadata.images = [{ url: 'https://s3.eu-central-1.amazonaws.com/img.hromadske.ua/posts/224808/opng/medium.jpg' }]
      const request = new chrome.cast.media.LoadRequest(mediaInfo)
      request.credentials = 'user-credentials'
      request.atvCredentials = 'atv-user-credentials'
      castSession.loadMedia(request).then(
        this.playerHandler.loaded.bind(this.playerHandler),
        (errorCode) => {
          this.playerState = PLAYER_STATE.ERROR
        },
      )
    }.bind(this)

    this.playerHandler.setTarget(playerTarget)

    this.playerHandler.play()
  }
}
/**
 * PlayerHandler
 */
class PlayerHandler {
  constructor(castPlayer) {
    this.target = {}

    this.setTarget = function (target) {
      this.target = target
    }

    this.play = function () {
      if (castPlayer.playerState !== PLAYER_STATE.PLAYING
        && castPlayer.playerState !== PLAYER_STATE.PAUSED
        && castPlayer.playerState !== PLAYER_STATE.LOADED) {
        this.load(castPlayer.src)
        return
      }

      this.target.play()
      castPlayer.playerState = PLAYER_STATE.PLAYING
    }

    this.pause = function () {
      if (castPlayer.playerState !== PLAYER_STATE.PLAYING) {
        return
      }

      this.target.pause()
      castPlayer.playerState = PLAYER_STATE.PAUSED
    }

    this.stop = function () {
      this.pause()
      castPlayer.playerState = PLAYER_STATE.STOPPED
    }

    this.load = function (src) {
      castPlayer.playerState = PLAYER_STATE.LOADING

      this.target.load(src)
    }

    this.loaded = function () {
      castPlayer.playerState = PLAYER_STATE.LOADED
    }
  }
}
