#include "platform/webview_platform.h"

#include <DispatcherQueue.h>
#include <shlobj.h>
#include <windows.graphics.capture.h>

#include <filesystem>

#include "util/logging.h"

namespace coreframe_flutter_windows {

WebviewPlatform::WebviewPlatform()
    : runtime_(std::make_unique<WinrtRuntime>(RO_INIT_SINGLETHREADED)) {
  if (runtime_->available()) {
    DispatcherQueueOptions options{sizeof(DispatcherQueueOptions),
                                   DQTYPE_THREAD_CURRENT, DQTAT_COM_STA};

    if (FAILED(runtime_->CreateDispatcherQueueController(
            options, dispatcher_queue_controller_.put()))) {
      util::LogWarning("Creating DispatcherQueueController failed.");
      return;
    }

    if (!IsGraphicsCaptureSessionSupported()) {
      util::LogWarning(
          "Windows::Graphics::Capture::GraphicsCaptureSession is not "
          "supported.");
      return;
    }

    graphics_context_ = std::make_unique<GraphicsContext>(runtime_.get());
    valid_ = graphics_context_->IsValid();
  }
}

bool WebviewPlatform::IsGraphicsCaptureSessionSupported() {
  HSTRING className;
  HSTRING_HEADER classNameHeader;

  if (FAILED(runtime_->CreateStringReference(
          RuntimeClass_Windows_Graphics_Capture_GraphicsCaptureSession,
          &className, &classNameHeader))) {
    return false;
  }

  ABI::Windows::Graphics::Capture::IGraphicsCaptureSessionStatics
      *capture_session_statics;
  if (FAILED(runtime_->GetActivationFactory(
          className,
          __uuidof(
              ABI::Windows::Graphics::Capture::IGraphicsCaptureSessionStatics),
          (void **)&capture_session_statics))) {
    return false;
  }

  boolean is_supported = false;
  if (FAILED(capture_session_statics->IsSupported(&is_supported))) {
    return false;
  }

  return !!is_supported;
}

std::optional<std::wstring> WebviewPlatform::GetDefaultDataDirectory() {
  PWSTR path_tmp;
  if (!SUCCEEDED(
          SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &path_tmp))) {
    return std::nullopt;
  }
  auto path = std::filesystem::path(path_tmp);
  CoTaskMemFree(path_tmp);

  wchar_t filename[MAX_PATH];
  GetModuleFileName(nullptr, filename, MAX_PATH);
  path /= "coreframe_flutter_windows";
  path /= std::filesystem::path(filename).stem();

  return path.wstring();
}

} // namespace coreframe_flutter_windows
