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

#include "app/os_exchange_data_provider_gtk.h"

#include <algorithm>

#include "app/gtk_dnd_util.h"
#include "base/file_path.h"
#include "base/utf_string_conversions.h"
#include "net/base/net_util.h"

OSExchangeDataProviderGtk::OSExchangeDataProviderGtk(
    int known_formats,
    const std::set<GdkAtom>& known_custom_formats)
    : known_formats_(known_formats),
      known_custom_formats_(known_custom_formats),
      formats_(0),
      drag_image_(NULL) {
}

OSExchangeDataProviderGtk::OSExchangeDataProviderGtk()
    : known_formats_(0),
      formats_(0),
      drag_image_(NULL) {
}

OSExchangeDataProviderGtk::~OSExchangeDataProviderGtk() {
  if (drag_image_)
    g_object_unref(drag_image_);
}

bool OSExchangeDataProviderGtk::HasDataForAllFormats(
    int formats,
    const std::set<GdkAtom>& custom_formats) const {
  if ((formats_ & formats) != formats)
    return false;
  for (std::set<GdkAtom>::iterator i = custom_formats.begin();
       i != custom_formats.end(); ++i) {
    if (pickle_data_.find(*i) == pickle_data_.end())
      return false;
  }
  return true;
}

GtkTargetList* OSExchangeDataProviderGtk::GetTargetList() const {
  GtkTargetList* targets = gtk_target_list_new(NULL, 0);

  if ((formats_ & OSExchangeData::STRING) != 0)
    gtk_target_list_add_text_targets(targets, OSExchangeData::STRING);

  if ((formats_ & OSExchangeData::URL) != 0) {
    gtk_target_list_add_uri_targets(targets, OSExchangeData::URL);
    gtk_target_list_add(
        targets,
        gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::CHROME_NAMED_URL),
        0,
        OSExchangeData::URL);
  }

  if ((formats_ & OSExchangeData::FILE_NAME) != 0)
    gtk_target_list_add_uri_targets(targets, OSExchangeData::FILE_NAME);

  for (PickleData::const_iterator i = pickle_data_.begin();
       i != pickle_data_.end(); ++i) {
    gtk_target_list_add(targets, i->first, 0, OSExchangeData::PICKLED_DATA);
  }

  return targets;
}

void OSExchangeDataProviderGtk::WriteFormatToSelection(
    int format,
    GtkSelectionData* selection) const {
  if ((format & OSExchangeData::STRING) != 0) {
    gtk_selection_data_set_text(
        selection,
        reinterpret_cast<const gchar*>(string_.c_str()),
        -1);
  }

  if ((format & OSExchangeData::URL) != 0) {
    // TODO: this should be pulled out of TabContentsDragSource into a common
    // place.
    Pickle pickle;
    pickle.WriteString(UTF16ToUTF8(title_));
    pickle.WriteString(url_.spec());
    gtk_selection_data_set(
        selection,
        gtk_dnd_util::GetAtomForTarget(gtk_dnd_util::CHROME_NAMED_URL),
        8,
        reinterpret_cast<const guchar*>(pickle.data()),
        pickle.size());

    gchar* uri_array[2];
    uri_array[0] = strdup(url_.spec().c_str());
    uri_array[1] = NULL;
    gtk_selection_data_set_uris(selection, uri_array);
    free(uri_array[0]);
  }

  if ((format & OSExchangeData::FILE_NAME) != 0) {
    gchar* uri_array[2];
    uri_array[0] =
        strdup(net::FilePathToFileURL(FilePath(filename_)).spec().c_str());
    uri_array[1] = NULL;
    gtk_selection_data_set_uris(selection, uri_array);
    free(uri_array[0]);
  }

  if ((format & OSExchangeData::PICKLED_DATA) != 0) {
    for (PickleData::const_iterator i = pickle_data_.begin();
         i != pickle_data_.end(); ++i) {
      const Pickle& data = i->second;
      gtk_selection_data_set(
          selection,
          i->first,
          8,
          reinterpret_cast<const guchar*>(data.data()),
          data.size());
    }
  }
}

void OSExchangeDataProviderGtk::SetString(const std::wstring& data) {
  string_ = WideToUTF16Hack(data);
  formats_ |= OSExchangeData::STRING;
}

void OSExchangeDataProviderGtk::SetURL(const GURL& url,
                                       const std::wstring& title) {
  url_ = url;
  title_ = WideToUTF16Hack(title);
  formats_ |= OSExchangeData::URL;
}

void OSExchangeDataProviderGtk::SetFilename(const std::wstring& full_path) {
  filename_ = WideToUTF8(full_path);
  formats_ |= OSExchangeData::FILE_NAME;
}

void OSExchangeDataProviderGtk::SetPickledData(GdkAtom format,
                                               const Pickle& data) {
  pickle_data_[format] = data;
  formats_ |= OSExchangeData::PICKLED_DATA;
}

bool OSExchangeDataProviderGtk::GetString(std::wstring* data) const {
  if ((formats_ & OSExchangeData::STRING) == 0)
    return false;
  *data = UTF16ToWideHack(string_);
  return true;
}

bool OSExchangeDataProviderGtk::GetURLAndTitle(GURL* url,
                                               std::wstring* title) const {
  if ((formats_ & OSExchangeData::URL) == 0) {
    title->clear();
    return GetPlainTextURL(url);
  }

  if (!url_.is_valid())
    return false;

  *url = url_;
  *title = UTF16ToWideHack(title_);
  return true;
}

bool OSExchangeDataProviderGtk::GetFilename(std::wstring* full_path) const {
  if ((formats_ & OSExchangeData::FILE_NAME) == 0)
    return false;
  *full_path = UTF8ToWide(filename_);
  return true;
}

bool OSExchangeDataProviderGtk::GetPickledData(GdkAtom format,
                                               Pickle* data) const {
  PickleData::const_iterator i = pickle_data_.find(format);
  if (i == pickle_data_.end())
    return false;

  *data = i->second;
  return true;
}

bool OSExchangeDataProviderGtk::HasString() const {
  return (known_formats_ & OSExchangeData::STRING) != 0 ||
         (formats_ & OSExchangeData::STRING) != 0;
}

bool OSExchangeDataProviderGtk::HasURL() const {
  if ((known_formats_ & OSExchangeData::URL) != 0 ||
      (formats_ & OSExchangeData::URL) != 0) {
    return true;
  }
  // No URL, see if we have plain text that can be parsed as a URL.
  return GetPlainTextURL(NULL);
}

bool OSExchangeDataProviderGtk::HasFile() const {
  return (known_formats_ & OSExchangeData::FILE_NAME) != 0 ||
         (formats_ & OSExchangeData::FILE_NAME) != 0;
  }

bool OSExchangeDataProviderGtk::HasCustomFormat(GdkAtom format) const {
  return known_custom_formats_.find(format) != known_custom_formats_.end() ||
         pickle_data_.find(format) != pickle_data_.end();
}

bool OSExchangeDataProviderGtk::GetPlainTextURL(GURL* url) const {
  if ((formats_ & OSExchangeData::STRING) == 0)
    return false;

  GURL test_url(string_);
  if (!test_url.is_valid())
    return false;

  if (url)
    *url = test_url;
  return true;
}

void OSExchangeDataProviderGtk::SetDragImage(GdkPixbuf* drag_image,
                                             const gfx::Point& cursor_offset) {
  if (drag_image_)
    g_object_unref(drag_image_);
  g_object_ref(drag_image);
  drag_image_ = drag_image;
  cursor_offset_ = cursor_offset;
}

///////////////////////////////////////////////////////////////////////////////
// OSExchangeData, public:

// static
OSExchangeData::Provider* OSExchangeData::CreateProvider() {
  return new OSExchangeDataProviderGtk();
}

GdkAtom OSExchangeData::RegisterCustomFormat(const std::string& type) {
  return gdk_atom_intern(type.c_str(), false);
}
