// Copyright (c) 2013 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/x/selection_utils.h"

#include <set>

#include "base/i18n/icu_string_conversions.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/x/x11_util.h"
#include "ui/gfx/x/x11_atom_cache.h"

namespace ui {

const char kMimeTypeMozillaURL[] = "text/x-moz-url";
const char kString[] = "STRING";
const char kText[] = "TEXT";
const char kTextPlain[] = "text/plain";
const char kTextPlainUtf8[] = "text/plain;charset=utf-8";
const char kUtf8String[] = "UTF8_STRING";

const char* kSelectionDataAtoms[] = {
  Clipboard::kMimeTypeHTML,
  kString,
  kText,
  kTextPlain,
  kTextPlainUtf8,
  kUtf8String,
  NULL
};

std::vector< ::Atom> GetTextAtomsFrom(const X11AtomCache* atom_cache) {
  std::vector< ::Atom> atoms;
  atoms.push_back(atom_cache->GetAtom(kUtf8String));
  atoms.push_back(atom_cache->GetAtom(kString));
  atoms.push_back(atom_cache->GetAtom(kText));
  atoms.push_back(atom_cache->GetAtom(kTextPlain));
  atoms.push_back(atom_cache->GetAtom(kTextPlainUtf8));
  return atoms;
}

std::vector< ::Atom> GetURLAtomsFrom(const X11AtomCache* atom_cache) {
  std::vector< ::Atom> atoms;
  atoms.push_back(atom_cache->GetAtom(Clipboard::kMimeTypeURIList));
  atoms.push_back(atom_cache->GetAtom(kMimeTypeMozillaURL));
  return atoms;
}

std::vector< ::Atom> GetURIListAtomsFrom(const X11AtomCache* atom_cache) {
  std::vector< ::Atom> atoms;
  atoms.push_back(atom_cache->GetAtom(Clipboard::kMimeTypeURIList));
  return atoms;
}

void GetAtomIntersection(const std::vector< ::Atom>& desired,
                         const std::vector< ::Atom>& offered,
                         std::vector< ::Atom>* output) {
  for (std::vector< ::Atom>::const_iterator it = desired.begin();
       it != desired.end(); ++it) {
    std::vector< ::Atom>::const_iterator jt =
      std::find(offered.begin(), offered.end(), *it);
    if (jt != offered.end())
      output->push_back(*it);
  }
}

void AddString16ToVector(const base::string16& str,
                         std::vector<unsigned char>* bytes) {
  const unsigned char* front =
      reinterpret_cast<const unsigned char*>(str.data());
  bytes->insert(bytes->end(), front, front + (str.size() * 2));
}

std::vector<std::string> ParseURIList(const SelectionData& data) {
  // uri-lists are newline separated file lists in URL encoding.
  std::string unparsed;
  data.AssignTo(&unparsed);

  std::vector<std::string> tokens;
  Tokenize(unparsed, "\n", &tokens);
  return tokens;
}

std::string RefCountedMemoryToString(
    const scoped_refptr<base::RefCountedMemory>& memory) {
  if (!memory.get()) {
    NOTREACHED();
    return std::string();
  }

  size_t size = memory->size();
  if (!size)
    return std::string();

  const unsigned char* front = memory->front();
  return std::string(reinterpret_cast<const char*>(front), size);
}

base::string16 RefCountedMemoryToString16(
    const scoped_refptr<base::RefCountedMemory>& memory) {
  if (!memory.get()) {
    NOTREACHED();
    return base::string16();
  }

  size_t size = memory->size();
  if (!size)
    return base::string16();

  const unsigned char* front = memory->front();
  return base::string16(reinterpret_cast<const base::char16*>(front), size / 2);
}

///////////////////////////////////////////////////////////////////////////////

SelectionFormatMap::SelectionFormatMap() {}

SelectionFormatMap::~SelectionFormatMap() {}

void SelectionFormatMap::Insert(
    ::Atom atom,
    const scoped_refptr<base::RefCountedMemory>& item) {
  data_.erase(atom);
  data_.insert(std::make_pair(atom, item));
}

ui::SelectionData SelectionFormatMap::GetFirstOf(
    const std::vector< ::Atom>& requested_types) const {
  for (std::vector< ::Atom>::const_iterator it = requested_types.begin();
       it != requested_types.end(); ++it) {
    const_iterator data_it = data_.find(*it);
    if (data_it != data_.end()) {
      return SelectionData(data_it->first, data_it->second);
    }
  }

  return SelectionData();
}

std::vector< ::Atom> SelectionFormatMap::GetTypes() const {
  std::vector< ::Atom> atoms;
  for (const_iterator it = data_.begin(); it != data_.end(); ++it)
    atoms.push_back(it->first);

  return atoms;
}

///////////////////////////////////////////////////////////////////////////////

SelectionData::SelectionData()
    : type_(None),
      atom_cache_(gfx::GetXDisplay(), kSelectionDataAtoms) {
}

SelectionData::SelectionData(
    ::Atom type,
    const scoped_refptr<base::RefCountedMemory>& memory)
    : type_(type),
      memory_(memory),
      atom_cache_(gfx::GetXDisplay(), kSelectionDataAtoms) {
}

SelectionData::SelectionData(const SelectionData& rhs)
    : type_(rhs.type_),
      memory_(rhs.memory_),
      atom_cache_(gfx::GetXDisplay(), kSelectionDataAtoms) {
}

SelectionData::~SelectionData() {}

SelectionData& SelectionData::operator=(const SelectionData& rhs) {
  type_ = rhs.type_;
  memory_ = rhs.memory_;
  // TODO(erg): In some future where we have to support multiple X Displays,
  // the following will also need to deal with the display.
  return *this;
}

bool SelectionData::IsValid() const {
  return type_ != None;
}

::Atom SelectionData::GetType() const {
  return type_;
}

const unsigned char* SelectionData::GetData() const {
  return memory_.get() ? memory_->front() : NULL;
}

size_t SelectionData::GetSize() const {
  return memory_.get() ? memory_->size() : 0;
}

std::string SelectionData::GetText() const {
  if (type_ == atom_cache_.GetAtom(kUtf8String) ||
      type_ == atom_cache_.GetAtom(kText) ||
      type_ == atom_cache_.GetAtom(kTextPlainUtf8)) {
    return RefCountedMemoryToString(memory_);
  } else if (type_ == atom_cache_.GetAtom(kString) ||
             type_ == atom_cache_.GetAtom(kTextPlain)) {
    std::string result;
    base::ConvertToUtf8AndNormalize(RefCountedMemoryToString(memory_),
                                    base::kCodepageLatin1,
                                    &result);
    return result;
  } else {
    // BTW, I looked at COMPOUND_TEXT, and there's no way we're going to
    // support that. Yuck.
    NOTREACHED();
    return std::string();
  }
}

base::string16 SelectionData::GetHtml() const {
  base::string16 markup;

  if (type_ == atom_cache_.GetAtom(Clipboard::kMimeTypeHTML)) {
    const unsigned char* data = GetData();
    size_t size = GetSize();

    // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is
    // UTF-16, otherwise assume UTF-8.
    if (size >= 2 &&
        reinterpret_cast<const uint16_t*>(data)[0] == 0xFEFF) {
      markup.assign(reinterpret_cast<const uint16_t*>(data) + 1,
                    (size / 2) - 1);
    } else {
      base::UTF8ToUTF16(reinterpret_cast<const char*>(data), size, &markup);
    }

    // If there is a terminating NULL, drop it.
    if (!markup.empty() && markup.at(markup.length() - 1) == '\0')
      markup.resize(markup.length() - 1);

    return markup;
  } else {
    NOTREACHED();
    return markup;
  }
}

void SelectionData::AssignTo(std::string* result) const {
  *result = RefCountedMemoryToString(memory_);
}

void SelectionData::AssignTo(base::string16* result) const {
  *result = RefCountedMemoryToString16(memory_);
}

}  // namespace ui
