// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "unix/ibus/selection_monitor.h"

#include <xcb/xcb.h>
#include <xcb/xfixes.h>

#include <cstdlib>
#include <memory>
#include <string>

#include "base/logging.h"
#include "base/mutex.h"
#include "base/thread.h"
#include "base/port.h"
#include "base/util.h"

namespace mozc {
namespace ibus {

namespace {

using std::unique_ptr;

class ScopedXcbGenericError {
 public:
  ScopedXcbGenericError()
      : error_(NULL) {
  }
  ~ScopedXcbGenericError() {
    free(error_);
    error_ = NULL;
  }
  const xcb_generic_error_t *get() const {
    return error_;
  }
  xcb_generic_error_t **mutable_get() {
    return &error_;
  }

 private:
  xcb_generic_error_t *error_;
};

template <typename T>
struct FreeDeleter {
  void operator()(T *ptr) const {
    free(ptr);
  }
};

// TODO(yukawa): Use template aliases when GCC 4.6 is retired.
typedef unique_ptr<xcb_get_property_reply_t,
                   FreeDeleter<xcb_get_property_reply_t>>
    ScopedXcbGetPropertyReply;
typedef unique_ptr<xcb_get_atom_name_reply_t,
                   FreeDeleter<xcb_get_atom_name_reply_t>>
    ScopedXcbGetAtomNameReply;
typedef unique_ptr<xcb_intern_atom_reply_t,
                   FreeDeleter<xcb_intern_atom_reply_t>>
    ScopedXcbInternAtomReply;
typedef unique_ptr<xcb_xfixes_query_version_reply_t,
                   FreeDeleter<xcb_xfixes_query_version_reply_t>>
    ScopedXcbXFixesQueqyVersionReply;

struct XcbAtoms {
  xcb_atom_t mozc_selection_monitor;
  xcb_atom_t net_wm_name;
  xcb_atom_t net_wm_pid;
  xcb_atom_t utf8_string;
  xcb_atom_t wm_client_machine;
  XcbAtoms()
      : mozc_selection_monitor(XCB_NONE),
        net_wm_name(XCB_NONE),
        net_wm_pid(XCB_NONE),
        utf8_string(XCB_NONE),
        wm_client_machine(XCB_NONE) {
  }
};

class SelectionMonitorServer {
 public:
  SelectionMonitorServer()
      : connection_(NULL),
        requestor_window_(0),
        root_window_(0),
        xfixes_first_event_(0),
        xcb_maximum_request_len_(0) {
  }

  ~SelectionMonitorServer() {
    Release();
  }

  bool Init() {
    connection_ = ::xcb_connect(NULL, NULL);
    if (connection_ == NULL) {
      return false;
    }

    if (!InitXFixes()) {
      Release();
      return false;
    }

    if (!InitAtoms()) {
      Release();
      return false;
    }

    const xcb_screen_t *screen =
        ::xcb_setup_roots_iterator(::xcb_get_setup(connection_)).data;

    requestor_window_ = ::xcb_generate_id(connection_);
    const uint32 mask = XCB_CW_EVENT_MASK;
    const uint32 values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
    root_window_ = screen->root;
    ::xcb_create_window(connection_, screen->root_depth,
                        requestor_window_, root_window_,
                        0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
                        screen->root_visual, mask, values);
    const uint32 xfixes_mask =
        XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
        XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY |
        XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE;
    ::xcb_xfixes_select_selection_input_checked(
        connection_, requestor_window_, XCB_ATOM_PRIMARY, xfixes_mask);
    ::xcb_flush(connection_);
    return true;
  }

  bool checkConnection() {
    if (!connection_) {
      return false;
    }
    if (::xcb_connection_has_error(connection_)) {
      LOG(ERROR) << "XCB connection has error.";
      connection_ = NULL;
      return false;
    }
    return true;
  }

  bool WaitForNextSelectionEvent(size_t max_bytes, SelectionInfo *next_info) {
    DCHECK(next_info);
    if (!connection_) {
      return false;
    }

    ::xcb_flush(connection_);
    unique_ptr<xcb_generic_event_t, void (*)(void*)> event(
        ::xcb_wait_for_event(connection_), &std::free);

    if (event.get() == NULL) {
      LOG(ERROR) << "NULL event returned.";
      return false;
    }

    const uint32_t response_type = (event->response_type & ~0x80);

    if (response_type ==
        (xfixes_first_event_ + XCB_XFIXES_SELECTION_NOTIFY)) {
      return OnXFixesSelectionNotify(event.get(), max_bytes, next_info);
    }

    if (response_type != XCB_SELECTION_NOTIFY) {
      VLOG(2) << "Ignored a message. response_type: " << response_type;
      return false;
    }

    return OnSelectionNotify(event.get(), max_bytes, next_info);
  }

  // Sends a harmless message to the |requestor_window_|. You can call this
  // method to awake a message pump thread which is waiting for the next
  // X11 message for |requestor_window_|.
  void SendNoopEventMessage() {
    if (!connection_ || !requestor_window_) {
      return;
    }

    // Send a dummy event so that the event pump can wake up.
    xcb_client_message_event_t event = {};
    event.response_type = XCB_CLIENT_MESSAGE;
    event.window = requestor_window_;
    event.format = 32;
    event.type  = XCB_NONE;
    ::xcb_send_event(connection_, false, requestor_window_,
                     XCB_EVENT_MASK_NO_EVENT,
                     reinterpret_cast<const char *>(&event));
    ::xcb_flush(connection_);
  }

 private:
  void Release() {
    if (connection_) {
      ::xcb_disconnect(connection_);
      connection_ = NULL;
    }
  }

  bool CreateAtom(const string name, xcb_atom_t *atom) const {
    DCHECK(atom);
    *atom = XCB_NONE;
    xcb_intern_atom_cookie_t cookie =
        ::xcb_intern_atom(connection_, false, name.size(), name.c_str());
    ScopedXcbInternAtomReply reply(
        ::xcb_intern_atom_reply(connection_, cookie, 0));
    if (reply.get() == NULL) {
      LOG(ERROR) << "xcb_intern_atom_reply returned NULL reply.";
      return false;
    }
    if (reply->atom == XCB_NONE) {
      return false;
    }
    *atom = reply->atom;
    return true;
  }

  bool InitAtoms() {
    return
        CreateAtom("MOZC_SEL_MON", &atoms_.mozc_selection_monitor) &&
        CreateAtom("UTF8_STRING", &atoms_.utf8_string) &&
        CreateAtom("_NET_WM_NAME", &atoms_.net_wm_name) &&
        CreateAtom("_NET_WM_PID", &atoms_.net_wm_pid) &&
        CreateAtom("WM_CLIENT_MACHINE", &atoms_.wm_client_machine);
  }

  bool InitXFixes() {
    const xcb_query_extension_reply_t
        *ext_reply = ::xcb_get_extension_data(connection_, &xcb_xfixes_id);
    if (ext_reply == NULL) {
      LOG(ERROR) << "xcb_get_extension_data returns NULL.";
      return false;
    }

    const xcb_xfixes_query_version_cookie_t xfixes_query_cookie =
        xcb_xfixes_query_version(
            connection_,
            XCB_XFIXES_MAJOR_VERSION,
            XCB_XFIXES_MINOR_VERSION);
    ScopedXcbGenericError xcb_error;
    ScopedXcbXFixesQueqyVersionReply xfixes_query(
        ::xcb_xfixes_query_version_reply(
            connection_, xfixes_query_cookie, xcb_error.mutable_get()));
    if (xcb_error.get() != NULL) {
      LOG(ERROR) << "xcb_xfixes_query_version_reply failed. error_code: "
                 << static_cast<uint32>(xcb_error.get()->error_code);
      return false;
    }
    if (xfixes_query.get() == NULL) {
      return false;
    }

    xfixes_first_event_ = ext_reply->first_event;
    LOG(INFO) << "XFixes ver: " << xfixes_query->major_version
              << "." << xfixes_query->major_version
              << ", first_event: " << xfixes_first_event_;

    xcb_maximum_request_len_ = ::xcb_get_maximum_request_length(connection_);
    if (xcb_maximum_request_len_ <= 0) {
      LOG(ERROR) << "Unexpected xcb maximum request length: "
                 << xcb_maximum_request_len_;
      return false;
    }

    return true;
  }

  string GetAtomName(xcb_atom_t atom) const {
    const xcb_get_atom_name_cookie_t cookie = ::xcb_get_atom_name(
        connection_, atom);
    ScopedXcbGenericError xcb_error;
    ScopedXcbGetAtomNameReply reply(
        ::xcb_get_atom_name_reply(
            connection_, cookie, xcb_error.mutable_get()));
    if (xcb_error.get() != NULL) {
      LOG(ERROR) << "xcb_get_atom_name_reply failed. error_code: "
                 << static_cast<uint32>(xcb_error.get()->error_code);
      return "";
    }
    if (reply.get() == NULL) {
      VLOG(2) << "reply is NULL";
      return "";
    }

    const char *ptr = ::xcb_get_atom_name_name(reply.get());
    const size_t len = ::xcb_get_atom_name_name_length(reply.get());
    return string(ptr, len);
  }

  bool GetByteArrayProperty(xcb_window_t window, xcb_atom_t property_atom,
                            xcb_atom_t property_type_atom,
                            size_t max_bytes,
                            string *retval) const {
    DCHECK(retval);
    retval->clear();
    size_t bytes_after = 0;
    int element_bit_size = 0;
    {
      const xcb_get_property_cookie_t cookie =
          ::xcb_get_property(connection_, false,
                             window,
                             property_atom,
                             property_type_atom,
                             0, 0);
      ScopedXcbGetPropertyReply reply(
          ::xcb_get_property_reply(connection_, cookie, 0));
      if (reply.get() == NULL) {
        VLOG(2) << "reply is NULL";
        return false;
      }
      if (reply->type == XCB_NONE) {
        LOG(ERROR) << "reply type is XCB_NONE";
        return false;
      }
      if (reply->type != property_type_atom) {
        LOG(ERROR) << "unexpected atom type: " << GetAtomName(reply->type);
        return false;
      }
      bytes_after = reply->bytes_after;
      element_bit_size = reply->format;
    }

    if (max_bytes < bytes_after) {
      LOG(WARNING) << "Exceeds size limit. Returns an empty string."
                   << " max_bytes: " << max_bytes
                   << ", bytes_after: " << bytes_after;
      *retval = "";
      return true;
    }

    if (element_bit_size == 0) {
      VLOG(1) << "element_bit_size is 0. Assuming byte-size data.";
      element_bit_size = 8;
    }

    if (element_bit_size != 8) {
      LOG(ERROR) << "Unsupported bit size: " << element_bit_size;
      return false;
    }

    int byte_offset = 0;

    while (bytes_after > 0) {
      const xcb_get_property_cookie_t cookie =
          ::xcb_get_property(connection_,
                             false,
                             window,
                             property_atom,
                             property_type_atom,
                             byte_offset,
                             max_bytes);
      ScopedXcbGetPropertyReply reply(
          ::xcb_get_property_reply(connection_, cookie, 0));
      if (reply.get() == NULL) {
        VLOG(2) << "reply is NULL";
        return false;
      }
      if (reply->format != element_bit_size) {
        LOG(ERROR) << "bit size changed: " << reply->format;
        return false;
      }
      bytes_after = reply->bytes_after;
      const char *data = reinterpret_cast<const char *>(
          ::xcb_get_property_value(reply.get()));
      const int length = ::xcb_get_property_value_length(reply.get());
      *retval += string(data, length);
      byte_offset += length;
    }
    return true;
  }

  template <typename T>
  bool GetCardinalProperty(xcb_window_t window, xcb_atom_t property_atom,
                           T *retval) const {
    *retval = 0;
    const xcb_get_property_cookie_t cookie =
        ::xcb_get_property(connection_, false,
                           window,
                           property_atom,
                           XCB_ATOM_CARDINAL,
                           0, sizeof(T) * 8);
    ScopedXcbGetPropertyReply reply(
        ::xcb_get_property_reply(connection_, cookie, 0));
    if (reply.get() == NULL) {
      VLOG(2) << "reply is NULL";
      return false;
    }

    if (reply->type != XCB_ATOM_CARDINAL) {
      LOG(ERROR) << "unexpected type: " << GetAtomName(reply->type);
      return false;
    }

    // All data should be read.
    if (reply->bytes_after != 0) {
      LOG(ERROR) << "unexpectedly " << reply->bytes_after
                 << " bytes data remain.";
      return false;
    }
    if (reply->format != 0 && (reply->format != sizeof(T) * 8)) {
      LOG(ERROR) << "unexpected bit size: " << reply->format;
      return false;
    }

    *retval = *reinterpret_cast<const T *>(
        ::xcb_get_property_value(reply.get()));
    return true;
  }

  bool OnXFixesSelectionNotify(const xcb_generic_event_t *event,
                               size_t max_bytes, SelectionInfo *next_info) {
    const xcb_xfixes_selection_notify_event_t *event_notify =
        reinterpret_cast<const xcb_xfixes_selection_notify_event_t *>(
            event);
    if (event_notify->selection != XCB_ATOM_PRIMARY) {
      VLOG(2) << "Ignored :" << GetAtomName(event_notify->selection);
      return false;
    }

    // Send request message for selection info.
    ::xcb_convert_selection(connection_, requestor_window_,
                            XCB_ATOM_PRIMARY, atoms_.utf8_string,
                            atoms_.mozc_selection_monitor,
                            XCB_CURRENT_TIME);

    last_request_info_.timestamp = event_notify->selection_timestamp;

    uint32_t net_wm_pid = 0;
    if (GetCardinalProperty(event_notify->owner,
                            atoms_.net_wm_pid,
                            &net_wm_pid)) {
      last_request_info_.process_id = net_wm_pid;
    }

    string net_wm_name;
    if (GetByteArrayProperty(event_notify->owner,
                             atoms_.net_wm_name,
                             atoms_.utf8_string,
                             max_bytes,
                             &net_wm_name)) {
      last_request_info_.window_title = net_wm_name;
    }

    string wm_client_machine;
    if (GetByteArrayProperty(event_notify->owner,
                             atoms_.wm_client_machine,
                             XCB_ATOM_STRING,
                             max_bytes,
                             &wm_client_machine)) {
      last_request_info_.machine_name = wm_client_machine;
    }

    *next_info = last_request_info_;
    return true;
  }

  bool OnSelectionNotify(const xcb_generic_event_t *event, size_t max_bytes,
                         SelectionInfo *next_info) {
    const xcb_selection_notify_event_t *event_notify =
        reinterpret_cast<const xcb_selection_notify_event_t *>(event);
    if (event_notify->selection != XCB_ATOM_PRIMARY) {
      VLOG(2) << "Ignored a message. selection type:"
              << event_notify->selection;
      return false;
    }

    if (event_notify->property == XCB_NONE) {
      VLOG(2) << "Ignored a message whose property type is XCB_NONE";
      return false;
    }

    string selected_text;
    if (!GetByteArrayProperty(event_notify->requestor,
                              event_notify->property,
                              atoms_.utf8_string,
                              max_bytes,
                              &selected_text)) {
      LOG(ERROR) << "Failed to retrieve selection text.";
      return false;
    }

    // Update the result.
    *next_info = last_request_info_;
    next_info->selected_text = selected_text;
    return true;
  }

  xcb_connection_t *connection_;
  xcb_window_t requestor_window_;
  xcb_window_t root_window_;
  uint32 xfixes_first_event_;
  uint32 xcb_maximum_request_len_;
  SelectionInfo last_request_info_;
  XcbAtoms atoms_;

  DISALLOW_COPY_AND_ASSIGN(SelectionMonitorServer);
};

class SelectionMonitorImpl : public SelectionMonitorInterface,
                             public Thread {
 public:
  SelectionMonitorImpl(SelectionMonitorServer *server, size_t max_text_bytes)
    : server_(server),
      max_text_bytes_(max_text_bytes),
      quit_(false) {
  }

  virtual ~SelectionMonitorImpl() {
    // Currently mozc::Thread cannot safely detach the attached thread since
    // the detached thread continues running on a heap allocated to this
    // object.
    // TODO(yukawa): Implement safer thread termination.
    if (Thread::IsRunning()) {
      QueryQuit();
      // TODO(yukawa): Add Wait method to mozc::Thread.
      Util::Sleep(100);
    }
  }

  // Implements SelectionMonitorInterface::StartMonitoring.
  virtual void StartMonitoring() {
    Thread::Start();
  }

  // Implements SelectionMonitorInterface::QueryQuit.
  virtual void QueryQuit() {
    if (Thread::IsRunning()) {
      quit_ = true;
      // Awake the message pump thread so that it can see the updated
      // |quit_| immediately.
      server_->SendNoopEventMessage();
    }
  }

  // Implements SelectionMonitorInterface::GetSelectionInfo.
  virtual SelectionInfo GetSelectionInfo() {
    SelectionInfo info;
    {
      scoped_lock l(&mutex_);
      info = last_selection_info_;
    }
    return info;
  }

  // Implements Thread::Run.
  virtual void Run() {
    while (!quit_) {
      if (!server_->checkConnection()) {
        scoped_lock l(&mutex_);
        last_selection_info_ = SelectionInfo();
        quit_ = true;
        break;
      }

      SelectionInfo next_info;
      // Note that this is blocking call and will not return until the next
      // X11 message is received. In order to interrupt, you can call
      // SendNoopEventMessage() method from other threads.
      if (server_->WaitForNextSelectionEvent(max_text_bytes_, &next_info)) {
        scoped_lock l(&mutex_);
        last_selection_info_ = next_info;
      }
    }
  }

 private:
  unique_ptr<SelectionMonitorServer> server_;
  const size_t max_text_bytes_;
  volatile bool quit_;
  Mutex mutex_;
  SelectionInfo last_selection_info_;

  DISALLOW_COPY_AND_ASSIGN(SelectionMonitorImpl);
};

}  // namespace

SelectionMonitorInterface::~SelectionMonitorInterface() {}

SelectionInfo::SelectionInfo()
    : timestamp(0), process_id(0) {
}

SelectionMonitorInterface *SelectionMonitorFactory::Create(
    size_t max_text_bytes) {
  unique_ptr<SelectionMonitorServer> server(new SelectionMonitorServer());
  if (!server->Init()) {
    return NULL;
  }
  return new SelectionMonitorImpl(server.release(), max_text_bytes);
}

}  // namespace ibus
}  // namespace mozc
