// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/shared/starboard/media/media_support_internal.h"

#include <sstream>

#include "starboard/common/scoped_ptr.h"
#include "starboard/configuration.h"
#include "starboard/media.h"
#include "starboard/once.h"
#include "starboard/shared/win32/error_utils.h"
#include "starboard/shared/win32/media_common.h"
#include "starboard/shared/win32/media_foundation_utils.h"
#include "starboard/shared/win32/media_transform.h"
#include "starboard/shared/win32/video_transform.h"
#include "starboard/shared/win32/wchar_utils.h"
#include "starboard/system.h"
#include "starboard/window.h"

// #define ENABLE_VP9_DECODER

using Microsoft::WRL::ComPtr;
using starboard::scoped_ptr;
using starboard::ScopedLock;
using starboard::shared::win32::CheckResult;
using starboard::shared::win32::kVideoFormat_YV12;
using starboard::shared::win32::MediaTransform;
using starboard::shared::win32::TryCreateVP9Transform;

namespace {

class VideoSupported {
 public:
  static VideoSupported* GetSingleton();
  bool IsVideoSupported(SbMediaVideoCodec video_codec,
                        int frame_width,
                        int frame_height,
                        int64_t bitrate,
                        int fps) {
    // Is resolution out of range?
    if (frame_width > max_width_ || frame_height > max_height_) {
      return false;
    }
    // Is bitrate in range?
    if (bitrate > SB_MEDIA_MAX_VIDEO_BITRATE_IN_BITS_PER_SECOND) {
      return false;
    }
    if (fps > 60) {
      return false;
    }
    if (video_codec == kSbMediaVideoCodecH264) {
      return true;
    }
    if (video_codec == kSbMediaVideoCodecVp9) {
      return IsVp9Supported(frame_width, frame_height);
    }
    return false;
  }

 private:
  bool AllowVp9Decoder() {
#ifdef ENABLE_VP9_DECODER
    return platform_supports_vp9_;
#else
    return false;
#endif
  }

  static bool DetectVp9Supported(int width, int height) {
    scoped_ptr<MediaTransform> vp9_decoder =
        TryCreateVP9Transform(kVideoFormat_YV12, width, height);
    return !!vp9_decoder.get();
  }

  static bool DetectPlatformIsXbox() {
    using starboard::shared::win32::platformStringToString;
    using Windows::Security::ExchangeActiveSyncProvisioning::
        EasClientDeviceInformation;

    EasClientDeviceInformation^ device_info =
          ref new EasClientDeviceInformation();

    const std::string product_name =
        platformStringToString(device_info->SystemProductName);

    return product_name.find("Xbox One") != std::string::npos;
  }

  bool IsVp9Supported(int width, int height) {
    if (!AllowVp9Decoder()) {
      return false;
    }
    // When width/height is zero then this is a special value to mean
    // IsVP9 available at all? Therefore detect the general case by
    // testing the specific case of 1024 x 768.
    if ((width == 0) && (height == 0)) {
      return DetectVp9Supported(1024, 768);
    }

    Key key = {width, height};
    ScopedLock lock(mutex_);
    auto it = vpn_size_cache_.find(key);
    if (it != vpn_size_cache_.end()) {
      return it->second;
    } else {
      const bool vp9_valid = DetectVp9Supported(width, height);
      vpn_size_cache_[key] = vp9_valid;
      return vp9_valid;
    }
  }

  VideoSupported() {
    platform_supports_vp9_ = DetectPlatformIsXbox();
    SbWindowOptions sb_window_options;
    SbWindowSetDefaultOptions(&sb_window_options);
    max_width_ = sb_window_options.size.width;
    max_height_ = sb_window_options.size.height;
  }

  struct Key {
    int width = 0;
    int height = 0;
    bool operator<(const Key& other) const {
      if (width != other.width) {
        return width < other.width;
      }
      return height < other.height;
    }
  };

  starboard::Mutex mutex_;
  using Vp9SizeCache = std::map<Key, bool>;
  Vp9SizeCache vpn_size_cache_;
  bool platform_supports_vp9_ = false;
  int max_width_ = 0;
  int max_height_ = 0;
};

SB_ONCE_INITIALIZE_FUNCTION(VideoSupported, VideoSupported::GetSingleton);

}  // namespace.

SB_EXPORT bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
                                       int frame_width,
                                       int frame_height,
                                       int64_t bitrate,
                                       int fps) {
  bool supported = VideoSupported::GetSingleton()->IsVideoSupported(
      video_codec, frame_width, frame_height, bitrate, fps);
  return supported;
}
