// Copyright (c) 2012 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 "ui/base/clipboard/clipboard.h"

#include "base/android/jni_string.h"
#include "base/lazy_instance.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "jni/Clipboard_jni.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/clipboard/clipboard_android_initialization.h"
#include "ui/gfx/size.h"

// TODO:(andrewhayden) Support additional formats in Android: Bitmap, URI, HTML,
// HTML+text now that Android's clipboard system supports them, then nuke the
// legacy implementation note below.

// Legacy implementation note:
// The Android clipboard system used to only support text format. So we used the
// Android system when some text was added or retrieved from the system. For
// anything else, we STILL store the value in some process wide static
// variable protected by a lock. So the (non-text) clipboard will only work
// within the same process.

using base::android::AttachCurrentThread;
using base::android::ClearException;
using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertUTF8ToJavaString;
using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;

namespace ui {

namespace {
// Various formats we support.
const char kPlainTextFormat[] = "text";
const char kHTMLFormat[] = "html";
const char kRTFFormat[] = "rtf";
const char kBitmapFormat[] = "bitmap";
const char kWebKitSmartPasteFormat[] = "webkit_smart";
const char kBookmarkFormat[] = "bookmark";
const char kMimeTypePepperCustomData[] = "chromium/x-pepper-custom-data";
const char kMimeTypeWebCustomData[] = "chromium/x-web-custom-data";

class ClipboardMap {
 public:
  ClipboardMap();
  std::string Get(const std::string& format);
  bool HasFormat(const std::string& format);
  void Set(const std::string& format, const std::string& data);
  void Clear();

 private:
  void SyncWithAndroidClipboard();
  std::map<std::string, std::string> map_;
  base::Lock lock_;

  // Java class and methods for the Android ClipboardManager.
  ScopedJavaGlobalRef<jobject> clipboard_manager_;
};
base::LazyInstance<ClipboardMap>::Leaky g_map = LAZY_INSTANCE_INITIALIZER;

ClipboardMap::ClipboardMap() {
  JNIEnv* env = AttachCurrentThread();
  DCHECK(env);

  // Get the context.
  jobject context = base::android::GetApplicationContext();
  DCHECK(context);

  ScopedJavaLocalRef<jobject> local_ref =
      Java_Clipboard_create(env, context);
  DCHECK(local_ref.obj());
  clipboard_manager_.Reset(env, local_ref.Release());
}

std::string ClipboardMap::Get(const std::string& format) {
  base::AutoLock lock(lock_);
  SyncWithAndroidClipboard();
  std::map<std::string, std::string>::const_iterator it = map_.find(format);
  return it == map_.end() ? std::string() : it->second;
}

bool ClipboardMap::HasFormat(const std::string& format) {
  base::AutoLock lock(lock_);
  SyncWithAndroidClipboard();
  return ContainsKey(map_, format);
}

void ClipboardMap::Set(const std::string& format, const std::string& data) {
  JNIEnv* env = AttachCurrentThread();
  base::AutoLock lock(lock_);
  SyncWithAndroidClipboard();

  map_[format] = data;
  if (format == kPlainTextFormat) {
    ScopedJavaLocalRef<jstring> str = ConvertUTF8ToJavaString(env, data);
    DCHECK(str.obj());

    Java_Clipboard_setText(env, clipboard_manager_.obj(), str.obj());
  } else if (format == kHTMLFormat) {
    // Android's API for storing HTML content on the clipboard requires a plain-
    // text representation to be available as well. ScopedClipboardWriter has a
    // stable order for setting clipboard data, ensuring that plain-text data
    // is available first. Do not write to the clipboard when only HTML data is
    // available, because otherwise others apps may not be able to paste it.
    if (!ContainsKey(map_, kPlainTextFormat))
      return;

    ScopedJavaLocalRef<jstring> html = ConvertUTF8ToJavaString(env, data);
    ScopedJavaLocalRef<jstring> text = ConvertUTF8ToJavaString(
        env, map_[kPlainTextFormat].c_str());

    DCHECK(html.obj() && text.obj());
    Java_Clipboard_setHTMLText(
        env, clipboard_manager_.obj(), html.obj(), text.obj());
  }
}

void ClipboardMap::Clear() {
  JNIEnv* env = AttachCurrentThread();
  base::AutoLock lock(lock_);
  map_.clear();
  Java_Clipboard_setText(env, clipboard_manager_.obj(), NULL);
}

// If the internal map contains a plain-text entry and it does not match that
// in the Android clipboard, clear the map and insert the Android text into it.
void ClipboardMap::SyncWithAndroidClipboard() {
  lock_.AssertAcquired();
  JNIEnv* env = AttachCurrentThread();

  std::map<std::string, std::string>::const_iterator it =
    map_.find(kPlainTextFormat);

  if (!Java_Clipboard_hasPlainText(env, clipboard_manager_.obj())) {
    if (it != map_.end())
      // We have plain text on this side, but Android doesn't. Nuke ours.
      map_.clear();
    return;
  }

  ScopedJavaLocalRef<jstring> java_string =
      Java_Clipboard_getCoercedText(env, clipboard_manager_.obj());

  if (!java_string.obj()) {
    // Tolerate a null value from the Java side, even though that should not
    // happen since hasPlainText has already returned true.
    // Should only happen if someone is using the clipboard on multiple
    // threads and clears it out after hasPlainText but before we get here...
    if (it != map_.end())
      // We have plain text on this side, but Android doesn't. Nuke ours.
      map_.clear();
    return;
  }

  // If Android text differs from ours (or we have none), then copy Android's.
  std::string android_string = ConvertJavaStringToUTF8(java_string);
  if (it == map_.end() || it->second != android_string) {
    map_.clear();
    map_[kPlainTextFormat] = android_string;
  }
}

}  // namespace

Clipboard::FormatType::FormatType() {
}

Clipboard::FormatType::FormatType(const std::string& native_format)
    : data_(native_format) {
}

Clipboard::FormatType::~FormatType() {
}

std::string Clipboard::FormatType::Serialize() const {
  return data_;
}

// static
Clipboard::FormatType Clipboard::FormatType::Deserialize(
    const std::string& serialization) {
  return FormatType(serialization);
}

bool Clipboard::FormatType::Equals(const FormatType& other) const {
  return data_ == other.data_;
}

Clipboard::Clipboard() {
  DCHECK(CalledOnValidThread());
}

Clipboard::~Clipboard() {
  DCHECK(CalledOnValidThread());
}

// Main entry point used to write several values in the clipboard.
void Clipboard::WriteObjects(Buffer buffer, const ObjectMap& objects) {
  DCHECK(CalledOnValidThread());
  DCHECK_EQ(buffer, BUFFER_STANDARD);
  g_map.Get().Clear();
  for (ObjectMap::const_iterator iter = objects.begin();
       iter != objects.end(); ++iter) {
    DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
  }
}

uint64 Clipboard::GetSequenceNumber(Clipboard::Buffer /* buffer */) {
  DCHECK(CalledOnValidThread());
  // TODO: implement this. For now this interface will advertise
  // that the clipboard never changes. That's fine as long as we
  // don't rely on this signal.
  return 0;
}

bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format,
                                  Clipboard::Buffer buffer) const {
  DCHECK(CalledOnValidThread());
  DCHECK_EQ(buffer, BUFFER_STANDARD);
  return g_map.Get().HasFormat(format.data());
}

void Clipboard::Clear(Buffer buffer) {
  DCHECK(CalledOnValidThread());
  DCHECK_EQ(buffer, BUFFER_STANDARD);
  g_map.Get().Clear();
}

void Clipboard::ReadAvailableTypes(Buffer buffer, std::vector<string16>* types,
                                   bool* contains_filenames) const {
  DCHECK(CalledOnValidThread());
  DCHECK_EQ(buffer, BUFFER_STANDARD);

  if (!types || !contains_filenames) {
    NOTREACHED();
    return;
  }

  NOTIMPLEMENTED();

  types->clear();
  *contains_filenames = false;
}

void Clipboard::ReadText(Clipboard::Buffer buffer, string16* result) const {
  DCHECK(CalledOnValidThread());
  DCHECK_EQ(buffer, BUFFER_STANDARD);
  std::string utf8;
  ReadAsciiText(buffer, &utf8);
  *result = UTF8ToUTF16(utf8);
}

void Clipboard::ReadAsciiText(Clipboard::Buffer buffer,
                              std::string* result) const {
  DCHECK(CalledOnValidThread());
  DCHECK_EQ(buffer, BUFFER_STANDARD);
  *result = g_map.Get().Get(kPlainTextFormat);
}

// Note: |src_url| isn't really used. It is only implemented in Windows
void Clipboard::ReadHTML(Clipboard::Buffer buffer,
                         string16* markup,
                         std::string* src_url,
                         uint32* fragment_start,
                         uint32* fragment_end) const {
  DCHECK(CalledOnValidThread());
  DCHECK_EQ(buffer, BUFFER_STANDARD);
  if (src_url)
    src_url->clear();

  std::string input = g_map.Get().Get(kHTMLFormat);
  *markup = UTF8ToUTF16(input);

  *fragment_start = 0;
  *fragment_end = static_cast<uint32>(markup->length());
}

void Clipboard::ReadRTF(Buffer buffer, std::string* result) const {
  DCHECK(CalledOnValidThread());
  NOTIMPLEMENTED();
}

SkBitmap Clipboard::ReadImage(Buffer buffer) const {
  DCHECK(CalledOnValidThread());
  DCHECK_EQ(buffer, BUFFER_STANDARD);
  std::string input = g_map.Get().Get(kBitmapFormat);

  SkBitmap bmp;
  if (!input.empty()) {
    DCHECK_LE(sizeof(gfx::Size), input.size());
    const gfx::Size* size = reinterpret_cast<const gfx::Size*>(input.data());

    bmp.setConfig(
        SkBitmap::kARGB_8888_Config, size->width(), size->height(), 0);
    bmp.allocPixels();

    int bm_size = size->width() * size->height() * 4;
    DCHECK_EQ(sizeof(gfx::Size) + bm_size, input.size());

    memcpy(bmp.getPixels(), input.data() + sizeof(gfx::Size), bm_size);
  }
  return bmp;
}

void Clipboard::ReadCustomData(Buffer buffer,
                               const string16& type,
                               string16* result) const {
  DCHECK(CalledOnValidThread());
  NOTIMPLEMENTED();
}

void Clipboard::ReadBookmark(string16* title, std::string* url) const {
  DCHECK(CalledOnValidThread());
  NOTIMPLEMENTED();
}

void Clipboard::ReadData(const Clipboard::FormatType& format,
                         std::string* result) const {
  DCHECK(CalledOnValidThread());
  *result = g_map.Get().Get(format.data());
}

// static
Clipboard::FormatType Clipboard::GetFormatType(
    const std::string& format_string) {
  return FormatType::Deserialize(format_string);
}

// static
const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kPlainTextFormat));
  return type;
}

// static
const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kPlainTextFormat));
  return type;
}

// static
const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kWebKitSmartPasteFormat));
  return type;
}

// static
const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kHTMLFormat));
  return type;
}

// static
const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kRTFFormat));
  return type;
}

// static
const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kBitmapFormat));
  return type;
}

// static
const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomData));
  return type;
}

// static
const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
  CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData));
  return type;
}

void Clipboard::WriteText(const char* text_data, size_t text_len) {
  g_map.Get().Set(kPlainTextFormat, std::string(text_data, text_len));
}

void Clipboard::WriteHTML(const char* markup_data,
                          size_t markup_len,
                          const char* url_data,
                          size_t url_len) {
  g_map.Get().Set(kHTMLFormat, std::string(markup_data, markup_len));
}

void Clipboard::WriteRTF(const char* rtf_data, size_t data_len) {
  NOTIMPLEMENTED();
}

// Note: according to other platforms implementations, this really writes the
// URL spec.
void Clipboard::WriteBookmark(const char* title_data, size_t title_len,
                              const char* url_data, size_t url_len) {
  g_map.Get().Set(kBookmarkFormat, std::string(url_data, url_len));
}

// Write an extra flavor that signifies WebKit was the last to modify the
// pasteboard. This flavor has no data.
void Clipboard::WriteWebSmartPaste() {
  g_map.Get().Set(kWebKitSmartPasteFormat, std::string());
}

// All platforms use gfx::Size for size data but it is passed as a const char*
// Further, pixel_data is expected to be 32 bits per pixel
// Note: we implement this to pass all unit tests but it is currently unclear
// how some code would consume this.
void Clipboard::WriteBitmap(const char* pixel_data, const char* size_data) {
  const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data);
  int bm_size = size->width() * size->height() * 4;

  std::string packed(size_data, sizeof(gfx::Size));
  packed += std::string(pixel_data, bm_size);
  g_map.Get().Set(kBitmapFormat, packed);
}

void Clipboard::WriteData(const Clipboard::FormatType& format,
                          const char* data_data, size_t data_len) {
  g_map.Get().Set(format.data(), std::string(data_data, data_len));
}

// See clipboard_android_initialization.h for more information.
bool RegisterClipboardAndroid(JNIEnv* env) {
  return RegisterNativesImpl(env);
}

} // namespace ui
