// Copyright (c) 2014 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_BROWSER_OSR_DRAGDROP_WIN_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_OSR_DRAGDROP_WIN_H_
#pragma once

// When generating projects with CMake the CEF_USE_ATL value will be defined
// automatically if using a supported Visual Studio version. Pass -DUSE_ATL=OFF
// to the CMake command-line to disable use of ATL.
// Uncomment this line to manually enable ATL support.
// #define CEF_USE_ATL 1

#if defined(CEF_USE_ATL)

#include <atlcomcli.h>
#include <objidl.h>
#include <stdio.h>

#include "tests/cefclient/browser/osr_dragdrop_events.h"

namespace client {

#define DEFAULT_QUERY_INTERFACE(__Class)                            \
  HRESULT __stdcall QueryInterface(const IID& iid, void** object) { \
    *object = nullptr;                                              \
    if (IsEqualIID(iid, IID_IUnknown)) {                            \
      IUnknown* obj = this;                                         \
      *object = obj;                                                \
    } else if (IsEqualIID(iid, IID_##__Class)) {                    \
      __Class* obj = this;                                          \
      *object = obj;                                                \
    } else {                                                        \
      return E_NOINTERFACE;                                         \
    }                                                               \
    AddRef();                                                       \
    return S_OK;                                                    \
  }
#define IUNKNOWN_IMPLEMENTATION                     \
  ULONG __stdcall AddRef() { return ++ref_count_; } \
  ULONG __stdcall Release() {                       \
    if (--ref_count_ == 0) {                        \
      delete this;                                  \
      return 0U;                                    \
    }                                               \
    return ref_count_;                              \
  }                                                 \
                                                    \
 protected:                                         \
  ULONG ref_count_;

class DropTargetWin : public IDropTarget {
 public:
  static CComPtr<DropTargetWin> Create(OsrDragEvents* callback, HWND hWnd);

  CefBrowserHost::DragOperationsMask StartDragging(
      CefRefPtr<CefBrowser> browser,
      CefRefPtr<CefDragData> drag_data,
      CefRenderHandler::DragOperationsMask allowed_ops,
      int x,
      int y);

  // IDropTarget implementation:
  HRESULT __stdcall DragEnter(IDataObject* data_object,
                              DWORD key_state,
                              POINTL cursor_position,
                              DWORD* effect);

  HRESULT __stdcall DragOver(DWORD key_state,
                             POINTL cursor_position,
                             DWORD* effect);

  HRESULT __stdcall DragLeave();

  HRESULT __stdcall Drop(IDataObject* data_object,
                         DWORD key_state,
                         POINTL cursor_position,
                         DWORD* effect);

  DEFAULT_QUERY_INTERFACE(IDropTarget)
  IUNKNOWN_IMPLEMENTATION

 protected:
  DropTargetWin(OsrDragEvents* callback, HWND hWnd)
      : ref_count_(0), callback_(callback), hWnd_(hWnd) {}
  virtual ~DropTargetWin() {}

 private:
  OsrDragEvents* callback_;
  HWND hWnd_;

  CefRefPtr<CefDragData> current_drag_data_;
};

class DropSourceWin : public IDropSource {
 public:
  static CComPtr<DropSourceWin> Create();

  // IDropSource implementation:
  HRESULT __stdcall GiveFeedback(DWORD dwEffect);

  HRESULT __stdcall QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState);

  DEFAULT_QUERY_INTERFACE(IDropSource)
  IUNKNOWN_IMPLEMENTATION

 protected:
  explicit DropSourceWin() : ref_count_(0) {}
  virtual ~DropSourceWin() {}
};

class DragEnumFormatEtc : public IEnumFORMATETC {
 public:
  static HRESULT CreateEnumFormatEtc(UINT cfmt,
                                     FORMATETC* afmt,
                                     IEnumFORMATETC** ppEnumFormatEtc);

  //
  // IEnumFormatEtc members
  //
  HRESULT __stdcall Next(ULONG celt,
                         FORMATETC* pFormatEtc,
                         ULONG* pceltFetched);
  HRESULT __stdcall Skip(ULONG celt);
  HRESULT __stdcall Reset(void);
  HRESULT __stdcall Clone(IEnumFORMATETC** ppEnumFormatEtc);

  //
  // Construction / Destruction
  //
  DragEnumFormatEtc(FORMATETC* pFormatEtc, int nNumFormats);
  virtual ~DragEnumFormatEtc();

  static void DeepCopyFormatEtc(FORMATETC* dest, FORMATETC* source);

  DEFAULT_QUERY_INTERFACE(IEnumFORMATETC)
  IUNKNOWN_IMPLEMENTATION

 private:
  ULONG m_nIndex;           // current enumerator index
  ULONG m_nNumFormats;      // number of FORMATETC members
  FORMATETC* m_pFormatEtc;  // array of FORMATETC objects
};

class DataObjectWin : public IDataObject {
 public:
  static CComPtr<DataObjectWin> Create(FORMATETC* fmtetc,
                                       STGMEDIUM* stgmed,
                                       int count);

  // IDataObject memberS
  HRESULT __stdcall GetDataHere(FORMATETC* pFormatEtc, STGMEDIUM* pmedium);
  HRESULT __stdcall QueryGetData(FORMATETC* pFormatEtc);
  HRESULT __stdcall GetCanonicalFormatEtc(FORMATETC* pFormatEct,
                                          FORMATETC* pFormatEtcOut);
  HRESULT __stdcall SetData(FORMATETC* pFormatEtc,
                            STGMEDIUM* pMedium,
                            BOOL fRelease);
  HRESULT __stdcall DAdvise(FORMATETC* pFormatEtc,
                            DWORD advf,
                            IAdviseSink*,
                            DWORD*);
  HRESULT __stdcall DUnadvise(DWORD dwConnection);
  HRESULT __stdcall EnumDAdvise(IEnumSTATDATA** ppEnumAdvise);

  HRESULT __stdcall EnumFormatEtc(DWORD dwDirection,
                                  IEnumFORMATETC** ppEnumFormatEtc);
  HRESULT __stdcall GetData(FORMATETC* pFormatEtc, STGMEDIUM* pMedium);

  DEFAULT_QUERY_INTERFACE(IDataObject)
  IUNKNOWN_IMPLEMENTATION

 protected:
  int m_nNumFormats;
  FORMATETC* m_pFormatEtc;
  STGMEDIUM* m_pStgMedium;

  static HGLOBAL DupGlobalMem(HGLOBAL hMem);

  int LookupFormatEtc(FORMATETC* pFormatEtc);

  explicit DataObjectWin(FORMATETC* fmtetc, STGMEDIUM* stgmed, int count);
  virtual ~DataObjectWin() {}
};

}  // namespace client

#endif  // defined(CEF_USE_ATL)

#endif  // CEF_TESTS_CEFCLIENT_BROWSER_OSR_DRAGDROP_WIN_H_
