/*! @license
 * Shaka Player
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

goog.provide('shaka.polyfill.MediaCapabilities');

goog.require('shaka.log');
goog.require('shaka.polyfill');
goog.require('shaka.util.Platform');


/**
 * @summary A polyfill to provide navigator.mediaCapabilities on all browsers.
 * This is necessary for Tizen 3, Xbox One and possibly others we have yet to
 * discover.
 */
shaka.polyfill.MediaCapabilities = class {
  /**
   * Install the polyfill if needed.
   * @suppress {const}
   */
  static install() {
    shaka.log.debug('MediaCapabilities: install');

    // Since MediaCapabilities is not fully supported on Chromecast yet, we
    // should always install polyfill for Chromecast.
    // TODO: re-evaluate MediaCapabilities in the future versions of Chromecast.
    if (!shaka.util.Platform.isChromecast() && navigator.mediaCapabilities) {
      shaka.log.debug(
          'MediaCapabilities: Native mediaCapabilities support found.');
      return;
    } else if (!window.MediaSource) {
      shaka.log.debug(
          'MediaSource must be available to install mediaCapabilities ',
          'polyfill.');
      return;
    }

    if (!navigator.mediaCapabilities) {
      navigator.mediaCapabilities = /** @type {!MediaCapabilities} */ ({});
    }
    navigator.mediaCapabilities.decodingInfo =
        shaka.polyfill.MediaCapabilities.decodingInfo_;
  }

  /**
   * @param {!MediaDecodingConfiguration} mediaDecodingConfig
   * @return {!Promise.<!MediaCapabilitiesDecodingInfo>}
   * @private
   */
  static async decodingInfo_(mediaDecodingConfig) {
    const res = {
      supported: false,
      powerEfficient: true,
      smooth: true,
      keySystemAccess: null,
      configuration: mediaDecodingConfig,
    };

    if (!mediaDecodingConfig) {
      return res;
    }

    // Use 'MediaSource.isTypeSupported' to check if the stream is supported.
    if (mediaDecodingConfig['video']) {
      const contentType = mediaDecodingConfig['video'].contentType;
      const isSupported = MediaSource.isTypeSupported(contentType);
      if (!isSupported) {
        return res;
      }
    }

    if (mediaDecodingConfig['audio']) {
      const contentType = mediaDecodingConfig['audio'].contentType;
      const isSupported = MediaSource.isTypeSupported(contentType);
      if (!isSupported) {
        return res;
      }
    }

    if (!mediaDecodingConfig.keySystemConfiguration) {
      // The variant is supported if it's unencrypted.
      res.supported = true;
      return Promise.resolve(res);
    } else {
      // Get the MediaKeySystemAccess for the key system.
      // Convert the MediaDecodingConfiguration object to a
      // MediaKeySystemConfiguration object.

      /** @type {MediaCapabilitiesKeySystemConfiguration} */
      const mediaCapkeySystemConfig =
          mediaDecodingConfig.keySystemConfiguration;
      const audioCapabilities = [];
      const videoCapabilities = [];

      if (mediaCapkeySystemConfig.audio) {
        const capability = {
          robustness: mediaCapkeySystemConfig.audio.robustness || '',
          contentType: mediaDecodingConfig.audio.contentType,
        };
        audioCapabilities.push(capability);
      }

      if (mediaCapkeySystemConfig.video) {
        const capability = {
          robustness: mediaCapkeySystemConfig.video.robustness || '',
          contentType: mediaDecodingConfig.video.contentType,
        };
        videoCapabilities.push(capability);
      }

      /** @type {MediaKeySystemConfiguration} */
      const mediaKeySystemConfig = {
        initDataTypes: [mediaCapkeySystemConfig.initDataType],
        distinctiveIdentifier: mediaCapkeySystemConfig.distinctiveIdentifier,
        persistentState: mediaCapkeySystemConfig.persistentState,
        sessionTypes: mediaCapkeySystemConfig.sessionTypes,
      };

      // Only add the audio video capablities if they have valid data.
      // Otherwise the query will fail.
      if (audioCapabilities.length) {
        mediaKeySystemConfig.audioCapabilities = audioCapabilities;
      }
      if (videoCapabilities.length) {
        mediaKeySystemConfig.videoCapabilities = videoCapabilities;
      }

      let keySystemAccess;
      try {
        keySystemAccess = await navigator.requestMediaKeySystemAccess(
            mediaCapkeySystemConfig.keySystem, [mediaKeySystemConfig]);
      } catch (e) {
        shaka.log.info('navigator.requestMediaKeySystemAccess failed.');
      }

      if (keySystemAccess) {
        res.supported = true;
        res.keySystemAccess = keySystemAccess;
      }
    }

    return res;
  }
};

// Install at a lower priority than MediaSource polyfill, so that we have
// MediaSource available first.
shaka.polyfill.register(shaka.polyfill.MediaCapabilities.install, -1);

@@ -1837,24 +1837,80 @@
 res;%0A    %7D%0A%0A
+    if (mediaDecodingConfig.type == 'media-source') %7B%0A  
     // Use '
@@ -1971,24 +1971,26 @@
  supported.%0A
+  
     if (medi
@@ -2015,32 +2015,34 @@
 ideo'%5D) %7B%0A      
+  
 const contentTyp
@@ -2079,32 +2079,34 @@
 '%5D.contentType;%0A
+  
       const isSu
@@ -2149,32 +2149,34 @@
 d(contentType);%0A
+  
       if (!isSup
@@ -2185,32 +2185,34 @@
 rted) %7B%0A        
+  
 return res;%0A    
@@ -2209,33 +2209,39 @@
  res;%0A      
+  
 %7D%0A    
+ 
+ 
 %7D%0A%0A
+  
     if (medi
@@ -2264,24 +2264,26 @@
 'audio'%5D) %7B%0A
+  
       const 
@@ -2340,24 +2340,26 @@
 Type;%0A      
+ 
+ 
 const isSupp
@@ -2410,24 +2410,26 @@
 ype);%0A      
+  
 if (!isSuppo
@@ -2436,32 +2436,34 @@
 rted) %7B%0A        
+  
 return res;%0A    
@@ -2456,33 +2456,682 @@
 turn res;%0A      
+ 
-%7D
+ %7D%0A      %7D%0A    %7D else if (mediaDecodingConfig.type == 'file') %7B%0A      if (mediaDecodingConfig%5B'video'%5D) %7B%0A        const contentType = mediaDecodingConfig%5B'video'%5D.contentType;%0A        const isSupported = shaka.util.Platform.supportsMediaType(contentType);%0A        if (!isSupported) %7B%0A          return res;%0A        %7D%0A      %7D%0A%0A      if (mediaDecodingConfig%5B'audio'%5D) %7B%0A        const contentType = mediaDecodingConfig%5B'audio'%5D.contentType;%0A        const isSupported = shaka.util.Platform.supportsMediaType(contentType);%0A        if (!isSupported) %7B%0A          return res;%0A        %7D%0A      %7D%0A    %7D else %7B%0A      // Otherwise not supported.%0A      return res;
 %0A    %7D%0A%0A    if (

Add support to file type in MediaCapabilities polyfill (#3569)