// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef PACKAGES_CAMERA_CAMERA_WINDOWS_WINDOWS_TEST_MOCKS_H_
#define PACKAGES_CAMERA_CAMERA_WINDOWS_WINDOWS_TEST_MOCKS_H_

#include <flutter/method_call.h>
#include <flutter/method_result_functions.h>
#include <flutter/standard_method_codec.h>
#include <flutter/texture_registrar.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <mfcaptureengine.h>

#include "camera.h"
#include "camera_plugin.h"
#include "capture_controller.h"
#include "capture_controller_listener.h"
#include "capture_engine_listener.h"

namespace camera_windows {
namespace test {

namespace {

using flutter::EncodableMap;
using flutter::EncodableValue;
using ::testing::_;

class MockMethodResult : public flutter::MethodResult<> {
 public:
  ~MockMethodResult() = default;

  MOCK_METHOD(void, SuccessInternal, (const EncodableValue* result),
              (override));
  MOCK_METHOD(void, ErrorInternal,
              (const std::string& error_code, const std::string& error_message,
               const EncodableValue* details),
              (override));
  MOCK_METHOD(void, NotImplementedInternal, (), (override));
};

class MockBinaryMessenger : public flutter::BinaryMessenger {
 public:
  ~MockBinaryMessenger() = default;

  MOCK_METHOD(void, Send,
              (const std::string& channel, const uint8_t* message,
               size_t message_size, flutter::BinaryReply reply),
              (const));

  MOCK_METHOD(void, SetMessageHandler,
              (const std::string& channel,
               flutter::BinaryMessageHandler handler),
              ());
};

class MockTextureRegistrar : public flutter::TextureRegistrar {
 public:
  MockTextureRegistrar() {
    ON_CALL(*this, RegisterTexture)
        .WillByDefault([this](flutter::TextureVariant* texture) -> int64_t {
          EXPECT_TRUE(texture);
          this->texture_ = texture;
          this->texture_id_ = 1000;
          return this->texture_id_;
        });

    ON_CALL(*this, UnregisterTexture)
        .WillByDefault([this](int64_t tid) -> bool {
          if (tid == this->texture_id_) {
            texture_ = nullptr;
            this->texture_id_ = -1;
            return true;
          }
          return false;
        });

    ON_CALL(*this, MarkTextureFrameAvailable)
        .WillByDefault([this](int64_t tid) -> bool {
          if (tid == this->texture_id_) {
            return true;
          }
          return false;
        });
  }

  ~MockTextureRegistrar() { texture_ = nullptr; }

  MOCK_METHOD(int64_t, RegisterTexture, (flutter::TextureVariant * texture),
              (override));

  MOCK_METHOD(bool, UnregisterTexture, (int64_t), (override));
  MOCK_METHOD(bool, MarkTextureFrameAvailable, (int64_t), (override));

  int64_t texture_id_ = -1;
  flutter::TextureVariant* texture_ = nullptr;
};

class MockCameraFactory : public CameraFactory {
 public:
  MockCameraFactory() {
    ON_CALL(*this, CreateCamera).WillByDefault([this]() {
      assert(this->pending_camera_);
      return std::move(this->pending_camera_);
    });
  }

  ~MockCameraFactory() = default;

  // Disallow copy and move.
  MockCameraFactory(const MockCameraFactory&) = delete;
  MockCameraFactory& operator=(const MockCameraFactory&) = delete;

  MOCK_METHOD(std::unique_ptr<Camera>, CreateCamera,
              (const std::string& device_id), (override));

  std::unique_ptr<Camera> pending_camera_;
};

class MockCamera : public Camera {
 public:
  MockCamera(const std::string& device_id)
      : device_id_(device_id), Camera(device_id){};

  ~MockCamera() = default;

  // Disallow copy and move.
  MockCamera(const MockCamera&) = delete;
  MockCamera& operator=(const MockCamera&) = delete;

  MOCK_METHOD(void, OnCreateCaptureEngineSucceeded, (int64_t texture_id),
              (override));
  MOCK_METHOD(std::unique_ptr<flutter::MethodResult<>>, GetPendingResultByType,
              (PendingResultType type));
  MOCK_METHOD(void, OnCreateCaptureEngineFailed, (const std::string& error),
              (override));

  MOCK_METHOD(void, OnStartPreviewSucceeded, (int32_t width, int32_t height),
              (override));
  MOCK_METHOD(void, OnStartPreviewFailed, (const std::string& error),
              (override));

  MOCK_METHOD(void, OnResumePreviewSucceeded, (), (override));
  MOCK_METHOD(void, OnResumePreviewFailed, (const std::string& error),
              (override));

  MOCK_METHOD(void, OnPausePreviewSucceeded, (), (override));
  MOCK_METHOD(void, OnPausePreviewFailed, (const std::string& error),
              (override));

  MOCK_METHOD(void, OnStartRecordSucceeded, (), (override));
  MOCK_METHOD(void, OnStartRecordFailed, (const std::string& error),
              (override));

  MOCK_METHOD(void, OnStopRecordSucceeded, (const std::string& file_path),
              (override));
  MOCK_METHOD(void, OnStopRecordFailed, (const std::string& error), (override));

  MOCK_METHOD(void, OnTakePictureSucceeded, (const std::string& file_path),
              (override));
  MOCK_METHOD(void, OnTakePictureFailed, (const std::string& error),
              (override));

  MOCK_METHOD(void, OnVideoRecordSucceeded,
              (const std::string& file_path, int64_t video_duration),
              (override));
  MOCK_METHOD(void, OnVideoRecordFailed, (const std::string& error),
              (override));
  MOCK_METHOD(void, OnCaptureError, (const std::string& error), (override));

  MOCK_METHOD(bool, HasDeviceId, (std::string & device_id), (const override));
  MOCK_METHOD(bool, HasCameraId, (int64_t camera_id), (const override));

  MOCK_METHOD(bool, AddPendingResult,
              (PendingResultType type, std::unique_ptr<MethodResult<>> result),
              (override));
  MOCK_METHOD(bool, HasPendingResultByType, (PendingResultType type),
              (const override));

  MOCK_METHOD(camera_windows::CaptureController*, GetCaptureController, (),
              (override));

  MOCK_METHOD(bool, InitCamera,
              (flutter::TextureRegistrar * texture_registrar,
               flutter::BinaryMessenger* messenger, bool record_audio,
               ResolutionPreset resolution_preset),
              (override));

  std::unique_ptr<CaptureController> capture_controller_;
  std::unique_ptr<MethodResult<>> pending_result_;
  std::string device_id_;
  int64_t camera_id_ = -1;
};

class MockCaptureControllerFactory : public CaptureControllerFactory {
 public:
  MockCaptureControllerFactory(){};
  virtual ~MockCaptureControllerFactory() = default;

  // Disallow copy and move.
  MockCaptureControllerFactory(const MockCaptureControllerFactory&) = delete;
  MockCaptureControllerFactory& operator=(const MockCaptureControllerFactory&) =
      delete;

  MOCK_METHOD(std::unique_ptr<CaptureController>, CreateCaptureController,
              (CaptureControllerListener * listener), (override));
};

class MockCaptureController : public CaptureController {
 public:
  ~MockCaptureController() = default;

  MOCK_METHOD(bool, InitCaptureDevice,
              (flutter::TextureRegistrar * texture_registrar,
               const std::string& device_id, bool record_audio,
               ResolutionPreset resolution_preset),
              (override));

  MOCK_METHOD(uint32_t, GetPreviewWidth, (), (const override));
  MOCK_METHOD(uint32_t, GetPreviewHeight, (), (const override));

  // Actions
  MOCK_METHOD(void, StartPreview, (), (override));
  MOCK_METHOD(void, ResumePreview, (), (override));
  MOCK_METHOD(void, PausePreview, (), (override));
  MOCK_METHOD(void, StartRecord,
              (const std::string& file_path, int64_t max_video_duration_ms),
              (override));
  MOCK_METHOD(void, StopRecord, (), (override));
  MOCK_METHOD(void, TakePicture, (const std::string& file_path), (override));
};

// MockCameraPlugin extends CameraPlugin behaviour a bit to allow adding cameras
// without creating them first with create message handler and mocking static
// system calls
class MockCameraPlugin : public CameraPlugin {
 public:
  MockCameraPlugin(flutter::TextureRegistrar* texture_registrar,
                   flutter::BinaryMessenger* messenger)
      : CameraPlugin(texture_registrar, messenger){};

  // Creates a plugin instance with the given CameraFactory instance.
  // Exists for unit testing with mock implementations.
  MockCameraPlugin(flutter::TextureRegistrar* texture_registrar,
                   flutter::BinaryMessenger* messenger,
                   std::unique_ptr<CameraFactory> camera_factory)
      : CameraPlugin(texture_registrar, messenger, std::move(camera_factory)){};

  ~MockCameraPlugin() = default;

  // Disallow copy and move.
  MockCameraPlugin(const MockCameraPlugin&) = delete;
  MockCameraPlugin& operator=(const MockCameraPlugin&) = delete;

  MOCK_METHOD(bool, EnumerateVideoCaptureDeviceSources,
              (IMFActivate * **devices, UINT32* count), (override));

  // Helper to add camera without creating it via CameraFactory for testing
  // purposes
  void AddCamera(std::unique_ptr<Camera> camera) {
    cameras_.push_back(std::move(camera));
  }
};

class MockCaptureSource : public IMFCaptureSource {
 public:
  MockCaptureSource(){};
  ~MockCaptureSource() = default;

  // IUnknown
  STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&ref_); }

  // IUnknown
  STDMETHODIMP_(ULONG) Release() {
    LONG ref = InterlockedDecrement(&ref_);
    if (ref == 0) {
      delete this;
    }
    return ref;
  }

  // IUnknown
  STDMETHODIMP_(HRESULT) QueryInterface(const IID& riid, void** ppv) {
    *ppv = nullptr;

    if (riid == IID_IMFCaptureSource) {
      *ppv = static_cast<IMFCaptureSource*>(this);
      ((IUnknown*)*ppv)->AddRef();
      return S_OK;
    }

    return E_NOINTERFACE;
  }

  MOCK_METHOD(HRESULT, GetCaptureDeviceSource,
              (MF_CAPTURE_ENGINE_DEVICE_TYPE mfCaptureEngineDeviceType,
               IMFMediaSource** ppMediaSource));
  MOCK_METHOD(HRESULT, GetCaptureDeviceActivate,
              (MF_CAPTURE_ENGINE_DEVICE_TYPE mfCaptureEngineDeviceType,
               IMFActivate** ppActivate));
  MOCK_METHOD(HRESULT, GetService,
              (REFIID rguidService, REFIID riid, IUnknown** ppUnknown));
  MOCK_METHOD(HRESULT, AddEffect,
              (DWORD dwSourceStreamIndex, IUnknown* pUnknown));

  MOCK_METHOD(HRESULT, RemoveEffect,
              (DWORD dwSourceStreamIndex, IUnknown* pUnknown));
  MOCK_METHOD(HRESULT, RemoveAllEffects, (DWORD dwSourceStreamIndex));
  MOCK_METHOD(HRESULT, GetAvailableDeviceMediaType,
              (DWORD dwSourceStreamIndex, DWORD dwMediaTypeIndex,
               IMFMediaType** ppMediaType));
  MOCK_METHOD(HRESULT, SetCurrentDeviceMediaType,
              (DWORD dwSourceStreamIndex, IMFMediaType* pMediaType));
  MOCK_METHOD(HRESULT, GetCurrentDeviceMediaType,
              (DWORD dwSourceStreamIndex, IMFMediaType** ppMediaType));
  MOCK_METHOD(HRESULT, GetDeviceStreamCount, (DWORD * pdwStreamCount));
  MOCK_METHOD(HRESULT, GetDeviceStreamCategory,
              (DWORD dwSourceStreamIndex,
               MF_CAPTURE_ENGINE_STREAM_CATEGORY* pStreamCategory));
  MOCK_METHOD(HRESULT, GetMirrorState,
              (DWORD dwStreamIndex, BOOL* pfMirrorState));
  MOCK_METHOD(HRESULT, SetMirrorState,
              (DWORD dwStreamIndex, BOOL fMirrorState));
  MOCK_METHOD(HRESULT, GetStreamIndexFromFriendlyName,
              (UINT32 uifriendlyName, DWORD* pdwActualStreamIndex));

 private:
  volatile ULONG ref_ = 0;
};

// Uses IMFMediaSourceEx which has SetD3DManager method.
class MockMediaSource : public IMFMediaSourceEx {
 public:
  MockMediaSource(){};
  ~MockMediaSource() = default;

  // IUnknown
  STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&ref_); }

  // IUnknown
  STDMETHODIMP_(ULONG) Release() {
    LONG ref = InterlockedDecrement(&ref_);
    if (ref == 0) {
      delete this;
    }
    return ref;
  }

  // IUnknown
  STDMETHODIMP_(HRESULT) QueryInterface(const IID& riid, void** ppv) {
    *ppv = nullptr;

    if (riid == IID_IMFMediaSource) {
      *ppv = static_cast<IMFMediaSource*>(this);
      ((IUnknown*)*ppv)->AddRef();
      return S_OK;
    }

    return E_NOINTERFACE;
  }

  // IMFMediaSource
  HRESULT GetCharacteristics(DWORD* dwCharacteristics) override {
    return E_NOTIMPL;
  }
  // IMFMediaSource
  HRESULT CreatePresentationDescriptor(
      IMFPresentationDescriptor** presentationDescriptor) override {
    return E_NOTIMPL;
  }
  // IMFMediaSource
  HRESULT Start(IMFPresentationDescriptor* presentationDescriptor,
                const GUID* guidTimeFormat,
                const PROPVARIANT* varStartPosition) override {
    return E_NOTIMPL;
  }
  // IMFMediaSource
  HRESULT Stop(void) override { return E_NOTIMPL; }
  // IMFMediaSource
  HRESULT Pause(void) override { return E_NOTIMPL; }
  // IMFMediaSource
  HRESULT Shutdown(void) override { return E_NOTIMPL; }

  // IMFMediaEventGenerator
  HRESULT GetEvent(DWORD dwFlags, IMFMediaEvent** event) override {
    return E_NOTIMPL;
  }
  // IMFMediaEventGenerator
  HRESULT BeginGetEvent(IMFAsyncCallback* callback,
                        IUnknown* unkState) override {
    return E_NOTIMPL;
  }
  // IMFMediaEventGenerator
  HRESULT EndGetEvent(IMFAsyncResult* result, IMFMediaEvent** event) override {
    return E_NOTIMPL;
  }
  // IMFMediaEventGenerator
  HRESULT QueueEvent(MediaEventType met, REFGUID guidExtendedType,
                     HRESULT hrStatus, const PROPVARIANT* value) override {
    return E_NOTIMPL;
  }

  // IMFMediaSourceEx
  HRESULT GetSourceAttributes(IMFAttributes** attributes) { return E_NOTIMPL; }
  // IMFMediaSourceEx
  HRESULT GetStreamAttributes(DWORD stream_id, IMFAttributes** attributes) {
    return E_NOTIMPL;
  }
  // IMFMediaSourceEx
  HRESULT SetD3DManager(IUnknown* manager) { return S_OK; }

 private:
  volatile ULONG ref_ = 0;
};

class MockCapturePreviewSink : public IMFCapturePreviewSink {
 public:
  // IMFCaptureSink
  MOCK_METHOD(HRESULT, GetOutputMediaType,
              (DWORD dwSinkStreamIndex, IMFMediaType** ppMediaType));

  // IMFCaptureSink
  MOCK_METHOD(HRESULT, GetService,
              (DWORD dwSinkStreamIndex, REFGUID rguidService, REFIID riid,
               IUnknown** ppUnknown));

  // IMFCaptureSink
  MOCK_METHOD(HRESULT, AddStream,
              (DWORD dwSourceStreamIndex, IMFMediaType* pMediaType,
               IMFAttributes* pAttributes, DWORD* pdwSinkStreamIndex));

  // IMFCaptureSink
  MOCK_METHOD(HRESULT, Prepare, ());

  // IMFCaptureSink
  MOCK_METHOD(HRESULT, RemoveAllStreams, ());

  // IMFCapturePreviewSink
  MOCK_METHOD(HRESULT, SetRenderHandle, (HANDLE handle));

  // IMFCapturePreviewSink
  MOCK_METHOD(HRESULT, SetRenderSurface, (IUnknown * pSurface));

  // IMFCapturePreviewSink
  MOCK_METHOD(HRESULT, UpdateVideo,
              (const MFVideoNormalizedRect* pSrc, const RECT* pDst,
               const COLORREF* pBorderClr));

  // IMFCapturePreviewSink
  MOCK_METHOD(HRESULT, SetSampleCallback,
              (DWORD dwStreamSinkIndex,
               IMFCaptureEngineOnSampleCallback* pCallback));

  // IMFCapturePreviewSink
  MOCK_METHOD(HRESULT, GetMirrorState, (BOOL * pfMirrorState));

  // IMFCapturePreviewSink
  MOCK_METHOD(HRESULT, SetMirrorState, (BOOL fMirrorState));

  // IMFCapturePreviewSink
  MOCK_METHOD(HRESULT, GetRotation,
              (DWORD dwStreamIndex, DWORD* pdwRotationValue));

  // IMFCapturePreviewSink
  MOCK_METHOD(HRESULT, SetRotation,
              (DWORD dwStreamIndex, DWORD dwRotationValue));

  // IMFCapturePreviewSink
  MOCK_METHOD(HRESULT, SetCustomSink, (IMFMediaSink * pMediaSink));

  // IUnknown
  STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&ref_); }

  // IUnknown
  STDMETHODIMP_(ULONG) Release() {
    LONG ref = InterlockedDecrement(&ref_);
    if (ref == 0) {
      delete this;
    }
    return ref;
  }

  // IUnknown
  STDMETHODIMP_(HRESULT) QueryInterface(const IID& riid, void** ppv) {
    *ppv = nullptr;

    if (riid == IID_IMFCapturePreviewSink) {
      *ppv = static_cast<IMFCapturePreviewSink*>(this);
      ((IUnknown*)*ppv)->AddRef();
      return S_OK;
    }

    return E_NOINTERFACE;
  }

  void SendFakeSample(uint8_t* src_buffer, uint32_t size) {
    assert(sample_callback_);
    ComPtr<IMFSample> sample;
    ComPtr<IMFMediaBuffer> buffer;
    HRESULT hr = MFCreateSample(&sample);

    if (SUCCEEDED(hr)) {
      hr = MFCreateMemoryBuffer(size, &buffer);
    }

    if (SUCCEEDED(hr)) {
      uint8_t* target_data;
      if (SUCCEEDED(buffer->Lock(&target_data, nullptr, nullptr))) {
        std::copy(src_buffer, src_buffer + size, target_data);
      }
      hr = buffer->Unlock();
    }

    if (SUCCEEDED(hr)) {
      hr = buffer->SetCurrentLength(size);
    }

    if (SUCCEEDED(hr)) {
      hr = sample->AddBuffer(buffer.Get());
    }

    if (SUCCEEDED(hr)) {
      sample_callback_->OnSample(sample.Get());
    }
  }

  ComPtr<IMFCaptureEngineOnSampleCallback> sample_callback_;

 private:
  ~MockCapturePreviewSink() = default;
  volatile ULONG ref_ = 0;
};

class MockCaptureRecordSink : public IMFCaptureRecordSink {
 public:
  // IMFCaptureSink
  MOCK_METHOD(HRESULT, GetOutputMediaType,
              (DWORD dwSinkStreamIndex, IMFMediaType** ppMediaType));

  // IMFCaptureSink
  MOCK_METHOD(HRESULT, GetService,
              (DWORD dwSinkStreamIndex, REFGUID rguidService, REFIID riid,
               IUnknown** ppUnknown));

  // IMFCaptureSink
  MOCK_METHOD(HRESULT, AddStream,
              (DWORD dwSourceStreamIndex, IMFMediaType* pMediaType,
               IMFAttributes* pAttributes, DWORD* pdwSinkStreamIndex));

  // IMFCaptureSink
  MOCK_METHOD(HRESULT, Prepare, ());

  // IMFCaptureSink
  MOCK_METHOD(HRESULT, RemoveAllStreams, ());

  // IMFCaptureRecordSink
  MOCK_METHOD(HRESULT, SetOutputByteStream,
              (IMFByteStream * pByteStream, REFGUID guidContainerType));

  // IMFCaptureRecordSink
  MOCK_METHOD(HRESULT, SetOutputFileName, (LPCWSTR fileName));

  // IMFCaptureRecordSink
  MOCK_METHOD(HRESULT, SetSampleCallback,
              (DWORD dwStreamSinkIndex,
               IMFCaptureEngineOnSampleCallback* pCallback));

  // IMFCaptureRecordSink
  MOCK_METHOD(HRESULT, SetCustomSink, (IMFMediaSink * pMediaSink));

  // IMFCaptureRecordSink
  MOCK_METHOD(HRESULT, GetRotation,
              (DWORD dwStreamIndex, DWORD* pdwRotationValue));

  // IMFCaptureRecordSink
  MOCK_METHOD(HRESULT, SetRotation,
              (DWORD dwStreamIndex, DWORD dwRotationValue));

  // IUnknown
  STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&ref_); }

  // IUnknown
  STDMETHODIMP_(ULONG) Release() {
    LONG ref = InterlockedDecrement(&ref_);
    if (ref == 0) {
      delete this;
    }
    return ref;
  }

  // IUnknown
  STDMETHODIMP_(HRESULT) QueryInterface(const IID& riid, void** ppv) {
    *ppv = nullptr;

    if (riid == IID_IMFCaptureRecordSink) {
      *ppv = static_cast<IMFCaptureRecordSink*>(this);
      ((IUnknown*)*ppv)->AddRef();
      return S_OK;
    }

    return E_NOINTERFACE;
  }

 private:
  ~MockCaptureRecordSink() = default;
  volatile ULONG ref_ = 0;
};

class MockCapturePhotoSink : public IMFCapturePhotoSink {
 public:
  // IMFCaptureSink
  MOCK_METHOD(HRESULT, GetOutputMediaType,
              (DWORD dwSinkStreamIndex, IMFMediaType** ppMediaType));

  // IMFCaptureSink
  MOCK_METHOD(HRESULT, GetService,
              (DWORD dwSinkStreamIndex, REFGUID rguidService, REFIID riid,
               IUnknown** ppUnknown));

  // IMFCaptureSink
  MOCK_METHOD(HRESULT, AddStream,
              (DWORD dwSourceStreamIndex, IMFMediaType* pMediaType,
               IMFAttributes* pAttributes, DWORD* pdwSinkStreamIndex));

  // IMFCaptureSink
  MOCK_METHOD(HRESULT, Prepare, ());

  // IMFCaptureSink
  MOCK_METHOD(HRESULT, RemoveAllStreams, ());

  // IMFCapturePhotoSink
  MOCK_METHOD(HRESULT, SetOutputFileName, (LPCWSTR fileName));

  // IMFCapturePhotoSink
  MOCK_METHOD(HRESULT, SetSampleCallback,
              (IMFCaptureEngineOnSampleCallback * pCallback));

  // IMFCapturePhotoSink
  MOCK_METHOD(HRESULT, SetOutputByteStream, (IMFByteStream * pByteStream));

  // IUnknown
  STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&ref_); }

  // IUnknown
  STDMETHODIMP_(ULONG) Release() {
    LONG ref = InterlockedDecrement(&ref_);
    if (ref == 0) {
      delete this;
    }
    return ref;
  }

  // IUnknown
  STDMETHODIMP_(HRESULT) QueryInterface(const IID& riid, void** ppv) {
    *ppv = nullptr;

    if (riid == IID_IMFCapturePhotoSink) {
      *ppv = static_cast<IMFCapturePhotoSink*>(this);
      ((IUnknown*)*ppv)->AddRef();
      return S_OK;
    }

    return E_NOINTERFACE;
  }

 private:
  ~MockCapturePhotoSink() = default;
  volatile ULONG ref_ = 0;
};

template <class T>
class FakeIMFAttributesBase : public T {
  static_assert(std::is_base_of<IMFAttributes, T>::value,
                "I must inherit from IMFAttributes");

  // IIMFAttributes
  HRESULT GetItem(REFGUID guidKey, PROPVARIANT* pValue) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE* pType) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT CompareItem(REFGUID guidKey, REFPROPVARIANT Value,
                      BOOL* pbResult) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT Compare(IMFAttributes* pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType,
                  BOOL* pbResult) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT GetUINT32(REFGUID guidKey, UINT32* punValue) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT GetUINT64(REFGUID guidKey, UINT64* punValue) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT GetDouble(REFGUID guidKey, double* pfValue) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT GetGUID(REFGUID guidKey, GUID* pguidValue) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT GetStringLength(REFGUID guidKey, UINT32* pcchLength) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize,
                    UINT32* pcchLength) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT GetAllocatedString(REFGUID guidKey, LPWSTR* ppwszValue,
                             UINT32* pcchLength) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT GetBlobSize(REFGUID guidKey, UINT32* pcbBlobSize) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT GetBlob(REFGUID guidKey, UINT8* pBuf, UINT32 cbBufSize,
                  UINT32* pcbBlobSize) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT GetAllocatedBlob(REFGUID guidKey, UINT8** ppBuf,
                           UINT32* pcbSize) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT GetUnknown(REFGUID guidKey, REFIID riid,
                     __RPC__deref_out_opt LPVOID* ppv) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT SetItem(REFGUID guidKey, REFPROPVARIANT Value) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT DeleteItem(REFGUID guidKey) override { return E_NOTIMPL; }

  // IIMFAttributes
  HRESULT DeleteAllItems(void) override { return E_NOTIMPL; }

  // IIMFAttributes
  HRESULT SetUINT32(REFGUID guidKey, UINT32 unValue) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT SetUINT64(REFGUID guidKey, UINT64 unValue) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT SetDouble(REFGUID guidKey, double fValue) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT SetGUID(REFGUID guidKey, REFGUID guidValue) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT SetString(REFGUID guidKey, LPCWSTR wszValue) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT SetBlob(REFGUID guidKey, const UINT8* pBuf,
                  UINT32 cbBufSize) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT SetUnknown(REFGUID guidKey, IUnknown* pUnknown) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT LockStore(void) override { return E_NOTIMPL; }

  // IIMFAttributes
  HRESULT UnlockStore(void) override { return E_NOTIMPL; }

  // IIMFAttributes
  HRESULT GetCount(UINT32* pcItems) override { return E_NOTIMPL; }

  // IIMFAttributes
  HRESULT GetItemByIndex(UINT32 unIndex, GUID* pguidKey,
                         PROPVARIANT* pValue) override {
    return E_NOTIMPL;
  }

  // IIMFAttributes
  HRESULT CopyAllItems(IMFAttributes* pDest) override { return E_NOTIMPL; }
};

class FakeMediaType : public FakeIMFAttributesBase<IMFMediaType> {
 public:
  FakeMediaType(GUID major_type, GUID sub_type, int width, int height)
      : major_type_(major_type),
        sub_type_(sub_type),
        width_(width),
        height_(height){};

  // IMFAttributes
  HRESULT GetUINT64(REFGUID key, UINT64* value) override {
    if (key == MF_MT_FRAME_SIZE) {
      *value = (int64_t)width_ << 32 | (int64_t)height_;
      return S_OK;
    } else if (key == MF_MT_FRAME_RATE) {
      *value = (int64_t)frame_rate_ << 32 | 1;
      return S_OK;
    }
    return E_FAIL;
  };

  // IMFAttributes
  HRESULT GetGUID(REFGUID key, GUID* value) override {
    if (key == MF_MT_MAJOR_TYPE) {
      *value = major_type_;
      return S_OK;
    } else if (key == MF_MT_SUBTYPE) {
      *value = sub_type_;
      return S_OK;
    }
    return E_FAIL;
  }

  // IIMFAttributes
  HRESULT CopyAllItems(IMFAttributes* pDest) override {
    pDest->SetUINT64(MF_MT_FRAME_SIZE,
                     (int64_t)width_ << 32 | (int64_t)height_);
    pDest->SetUINT64(MF_MT_FRAME_RATE, (int64_t)frame_rate_ << 32 | 1);
    pDest->SetGUID(MF_MT_MAJOR_TYPE, major_type_);
    pDest->SetGUID(MF_MT_SUBTYPE, sub_type_);
    return S_OK;
  }

  // IMFMediaType
  HRESULT STDMETHODCALLTYPE GetMajorType(GUID* pguidMajorType) override {
    return E_NOTIMPL;
  };

  // IMFMediaType
  HRESULT STDMETHODCALLTYPE IsCompressedFormat(BOOL* pfCompressed) override {
    return E_NOTIMPL;
  }

  // IMFMediaType
  HRESULT STDMETHODCALLTYPE IsEqual(IMFMediaType* pIMediaType,
                                    DWORD* pdwFlags) override {
    return E_NOTIMPL;
  }

  // IMFMediaType
  HRESULT STDMETHODCALLTYPE GetRepresentation(
      GUID guidRepresentation, LPVOID* ppvRepresentation) override {
    return E_NOTIMPL;
  }

  // IMFMediaType
  HRESULT STDMETHODCALLTYPE FreeRepresentation(
      GUID guidRepresentation, LPVOID pvRepresentation) override {
    return E_NOTIMPL;
  }

  // IUnknown
  STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&ref_); }

  // IUnknown
  STDMETHODIMP_(ULONG) Release() {
    LONG ref = InterlockedDecrement(&ref_);
    if (ref == 0) {
      delete this;
    }
    return ref;
  }

  // IUnknown
  STDMETHODIMP_(HRESULT) QueryInterface(const IID& riid, void** ppv) {
    *ppv = nullptr;

    if (riid == IID_IMFMediaType) {
      *ppv = static_cast<IMFMediaType*>(this);
      ((IUnknown*)*ppv)->AddRef();
      return S_OK;
    }

    return E_NOINTERFACE;
  }

 private:
  ~FakeMediaType() = default;
  volatile ULONG ref_ = 0;
  const GUID major_type_;
  const GUID sub_type_;
  const int width_;
  const int height_;
  const int frame_rate_ = 30;
};

class MockCaptureEngine : public IMFCaptureEngine {
 public:
  MockCaptureEngine() {
    ON_CALL(*this, Initialize)
        .WillByDefault([this](IMFCaptureEngineOnEventCallback* callback,
                              IMFAttributes* attributes, IUnknown* audioSource,
                              IUnknown* videoSource) -> HRESULT {
          EXPECT_TRUE(callback);
          EXPECT_TRUE(attributes);
          EXPECT_TRUE(videoSource);
          // audioSource is allowed to be nullptr;
          callback_ = callback;
          videoSource_ = reinterpret_cast<IMFMediaSource*>(videoSource);
          audioSource_ = reinterpret_cast<IMFMediaSource*>(audioSource);
          initialized_ = true;
          return S_OK;
        });
  };

  virtual ~MockCaptureEngine() = default;

  MOCK_METHOD(HRESULT, Initialize,
              (IMFCaptureEngineOnEventCallback * callback,
               IMFAttributes* attributes, IUnknown* audioSource,
               IUnknown* videoSource));
  MOCK_METHOD(HRESULT, StartPreview, ());
  MOCK_METHOD(HRESULT, StopPreview, ());
  MOCK_METHOD(HRESULT, StartRecord, ());
  MOCK_METHOD(HRESULT, StopRecord,
              (BOOL finalize, BOOL flushUnprocessedSamples));
  MOCK_METHOD(HRESULT, TakePhoto, ());
  MOCK_METHOD(HRESULT, GetSink,
              (MF_CAPTURE_ENGINE_SINK_TYPE type, IMFCaptureSink** sink));
  MOCK_METHOD(HRESULT, GetSource, (IMFCaptureSource * *ppSource));

  // IUnknown
  STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&ref_); }

  // IUnknown
  STDMETHODIMP_(ULONG) Release() {
    LONG ref = InterlockedDecrement(&ref_);
    if (ref == 0) {
      delete this;
    }
    return ref;
  }

  // IUnknown
  STDMETHODIMP_(HRESULT) QueryInterface(const IID& riid, void** ppv) {
    *ppv = nullptr;

    if (riid == IID_IMFCaptureEngine) {
      *ppv = static_cast<IMFCaptureEngine*>(this);
      ((IUnknown*)*ppv)->AddRef();
      return S_OK;
    }

    return E_NOINTERFACE;
  }

  void CreateFakeEvent(HRESULT hrStatus, GUID event_type) {
    EXPECT_TRUE(initialized_);
    ComPtr<IMFMediaEvent> event;
    MFCreateMediaEvent(MEExtendedType, event_type, hrStatus, nullptr, &event);
    if (callback_) {
      callback_->OnEvent(event.Get());
    }
  }

  ComPtr<IMFCaptureEngineOnEventCallback> callback_;
  ComPtr<IMFMediaSource> videoSource_;
  ComPtr<IMFMediaSource> audioSource_;
  volatile ULONG ref_ = 0;
  bool initialized_ = false;
};

#define MOCK_DEVICE_ID "mock_device_id"
#define MOCK_CAMERA_NAME "mock_camera_name <" MOCK_DEVICE_ID ">"
#define MOCK_INVALID_CAMERA_NAME "invalid_camera_name"

}  // namespace
}  // namespace test
}  // namespace camera_windows

#endif  // PACKAGES_CAMERA_CAMERA_WINDOWS_WINDOWS_TEST_MOCKS_H_
