// Copyright 2017 The Cobalt Authors. 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.

#ifndef STARBOARD_SHARED_WIN32_DRM_SYSTEM_PLAYREADY_H_
#define STARBOARD_SHARED_WIN32_DRM_SYSTEM_PLAYREADY_H_

#include <mfapi.h>
#include <mfidl.h>
#include <wrl.h>
#include <wrl/client.h>

#include <functional>
#include <map>
#include <string>

#include "starboard/common/mutex.h"
#include "starboard/common/ref_counted.h"
#include "starboard/shared/starboard/drm/drm_system_internal.h"
#include "starboard/shared/starboard/thread_checker.h"

namespace starboard {
namespace shared {
namespace win32 {

// Adapts PlayReady decryption module to Starboard's |SbDrmSystem|.
class DrmSystemPlayready : public SbDrmSystemPrivate {
 public:
  typedef std::function<bool()> EnableOutputProtectionFunc;

  class License : public RefCountedThreadSafe<License> {
   public:
    static scoped_refptr<License> Create(const void* initialization_data,
                                         int initialization_data_size);

    virtual ~License() {}

    virtual GUID key_id() const = 0;
    virtual bool usable() const = 0;
    virtual std::string license_challenge() const = 0;
    virtual Microsoft::WRL::ComPtr<IMFTransform> decryptor() = 0;
    virtual void UpdateLicense(const void* license, int license_size) = 0;
    virtual bool IsHDCPRequired() = 0;
  };

  DrmSystemPlayready(
      void* context,
      EnableOutputProtectionFunc enable_output_protection_func,
      SbDrmSessionUpdateRequestFunc session_update_request_callback,
      SbDrmSessionUpdatedFunc session_updated_callback,
      SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback,
      SbDrmSessionClosedFunc session_closed_callback);
  ~DrmSystemPlayready() override;

  static bool IsKeySystemSupported(const char* key_system);

  // From |SbDrmSystemPrivate|.
  void GenerateSessionUpdateRequest(int ticket,
                                    const char* type,
                                    const void* initialization_data,
                                    int initialization_data_size) override;

  void UpdateSession(int ticket,
                     const void* key,
                     int key_size,
                     const void* session_id,
                     int session_id_size) override;

  void CloseSession(const void* session_id, int session_id_size) override;

  DecryptStatus Decrypt(InputBuffer* buffer) override;

  // Used by audio and video decoders to retrieve the decryptors.
  scoped_refptr<License> GetLicense(const uint8_t* key_id, int key_id_size);

  void OnUwpResume();

  bool IsServerCertificateUpdatable() override { return false; }
  void UpdateServerCertificate(int ticket,
                               const void* certificate,
                               int certificate_size) override {}

  const void* GetMetrics(int* size) override { return NULL; }

 private:
  std::string GenerateAndAdvanceSessionId();
  // Note: requires mutex_ to be held
  void ReportKeyStatusChanged_Locked(const std::string& session_id);

  ::starboard::shared::starboard::ThreadChecker thread_checker_;

  void* context_;
  const EnableOutputProtectionFunc enable_output_protection_func_;
  const SbDrmSessionUpdateRequestFunc session_update_request_callback_;
  const SbDrmSessionUpdatedFunc session_updated_callback_;
  const SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback_;
  const SbDrmSessionClosedFunc session_closed_callback_;
  int current_session_id_ = 1;

  std::map<std::string, scoped_refptr<License> > pending_requests_;

  // |successful_requests_| can be accessed from more than one thread.  Guard
  // it by a mutex.
  Mutex mutex_;

  struct LicenseInfo {
    LicenseInfo(SbDrmKeyStatus status, const scoped_refptr<License>& license)
        : status_(status), license_(license) {}
    LicenseInfo() : status_(kSbDrmKeyStatusError) {}

    SbDrmKeyStatus status_;
    scoped_refptr<License> license_;
  };

  std::map<std::string, LicenseInfo> successful_requests_;
};

}  // namespace win32
}  // namespace shared
}  // namespace starboard

#endif  // STARBOARD_SHARED_WIN32_DRM_SYSTEM_PLAYREADY_H_
