/* Copyright (C) 2018 The gtkmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 */

#include <glibmm/object.h>
#include <giomm/asyncresult.h>
#include <gdkmm/enums.h>

_DEFS(gdkmm,gdk)
_PINCLUDE(glibmm/private/object_p.h)

namespace Gio
{
class GDKMM_API Cancellable;
class GDKMM_API InputStream;
}

namespace Gdk
{
class GDKMM_API ContentFormats;
class GDKMM_API Device;
class GDKMM_API Drag;
class GDKMM_API Display;
class GDKMM_API Surface;

/** A %Gdk::Drop object represents the target of an ongoing DND operation.
 *
 * Possible drop sites get informed about the status of the ongoing drag
 * operation with events of type Gdk::Event::Type::DRAG_ENTER,
 * Gdk::Event::Type::DRAG_LEAVE, Gdk::Event::Type::DRAG_MOTION and
 * Gdk::Event::Type::DROP_START. The %Gdk::Drop object can be obtained
 * from a DND event using Gdk::Event::get_dnd_drop().
 *
 * The actual data transfer is initiated from the target side via an async
 * read, using one of the %Gdk::Drop methods for this purpose:
 * read_async() or read_value_async().
 *
 * GTK provides a higher level abstraction based on top of these functions,
 * and so they are not normally needed in GTK applications.
 *
 * @newin{3,94}
 */
class GDKMM_API Drop : public Glib::Object
{
  _CLASS_GOBJECT(Drop, GdkDrop, GDK_DROP, Glib::Object, GObject, , , GDKMM_API)
  _DO_NOT_DERIVE_GTYPE dnl// GdkDrop is an internal type
  _ABI_AS_WITH_DERIVED_GTYPE dnl// Remove when we can break ABI

public:
  _WRAP_METHOD(Glib::RefPtr<Display> get_display(), gdk_drop_get_display, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Display> get_display() const, gdk_drop_get_display, refreturn, constversion)

  _WRAP_METHOD(Glib::RefPtr<Device> get_device(), gdk_drop_get_device, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Device> get_device() const, gdk_drop_get_device, refreturn, constversion)

  _WRAP_METHOD(Glib::RefPtr<Surface> get_surface(), gdk_drop_get_surface, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Surface> get_surface() const, gdk_drop_get_surface, refreturn, constversion)

  _WRAP_METHOD(Glib::RefPtr<ContentFormats> get_formats(), gdk_drop_get_formats, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const ContentFormats> get_formats() const, gdk_drop_get_formats, refreturn, constversion)

  _WRAP_METHOD(DragAction get_actions() const, gdk_drop_get_actions)

  _WRAP_METHOD(Glib::RefPtr<Drag> get_drag(), gdk_drop_get_drag, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Drag> get_drag() const, gdk_drop_get_drag, refreturn, constversion)

  _WRAP_METHOD(void status(DragAction actions, DragAction preferred), gdk_drop_status)
  /** Indicates that a drop will not be accepted.
   * This function may be called by the drag destination in response to
   * Gdk::Event::Type::DRAG_ENTER or Gdk::Event::Type::DRAG_MOTION events.
   * Alternatively, call status() to indicate which drag actions will be accepted.
   */
  void refuse();

  _WRAP_METHOD(void finish(DragAction action), gdk_drop_finish)
  /** Ends the drag operation and indicates that the operation failed.
   * Alternatively, call finish() to indicate which drag action was performed.
   */ 
  void failed();

#m4 _CONVERSION(`const std::vector<Glib::ustring>&',`const char**',`Glib::ArrayHandler<Glib::ustring>::vector_to_array($3).data()')
  _WRAP_METHOD(void read_async(const std::vector<Glib::ustring>& mime_types, int io_priority,
    const Gio::SlotAsyncReady& slot{callback}, const Glib::RefPtr<Gio::Cancellable>& cancellable{.?}),
    gdk_drop_read_async, slot_name slot, slot_callback gdkmm_SignalProxy_async_callback)
#m4 _INITIALIZATION(`Glib::ustring&',`const char*',`$3 = Glib::convert_const_gchar_ptr_to_ustring($4)')
  _WRAP_METHOD(Glib::RefPtr<Gio::InputStream> read_finish(const Glib::RefPtr<Gio::AsyncResult>& result,
    Glib::ustring& out_mime_type{>>}), gdk_drop_read_finish, errthrow)

  _WRAP_METHOD(void read_value_async(GType type, int io_priority,
    const Gio::SlotAsyncReady& slot{callback}, const Glib::RefPtr<Gio::Cancellable>& cancellable{.?}),
    gdk_drop_read_value_async, slot_name slot, slot_callback gdkmm_SignalProxy_async_callback)
  _WRAP_METHOD_DOCS_ONLY(gdk_drop_read_value_finish)
  Glib::ValueBase read_value_finish(const Glib::RefPtr<Gio::AsyncResult>& result);

  _WRAP_PROPERTY("actions", DragAction)
  _WRAP_PROPERTY("device", Glib::RefPtr<Device>)
  _WRAP_PROPERTY("display", Glib::RefPtr<Display>)
  _WRAP_PROPERTY("drag", Glib::RefPtr<Drag>)
  _WRAP_PROPERTY("formats", Glib::RefPtr<ContentFormats>)
  _WRAP_PROPERTY("surface", Glib::RefPtr<Surface>)

  // There are no signals or public vfuncs.
};

} // namespace Gdk
