// 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 "renderer/unix/unix_server.h"

#include <fcntl.h>
#include <unistd.h>

#include <memory>

#include "base/logging.h"
#include "renderer/renderer_command.pb.h"
#include "renderer/unix/window_manager.h"

using std::unique_ptr;

namespace mozc {
namespace renderer {
namespace gtk {
namespace {

gboolean mozc_prepare(GSource *source, int *timeout) {
  *timeout = -1;
  return FALSE;
}

gboolean mozc_check(GSource *source) {
  UnixServer::MozcWatchSource *watch
      = reinterpret_cast<UnixServer::MozcWatchSource*>(source);
  return watch->poll_fd.revents != 0;
}

gboolean mozc_dispatch(GSource *source, GSourceFunc callback,
                       gpointer user_data) {
  UnixServer::MozcWatchSource *watch
      = reinterpret_cast<UnixServer::MozcWatchSource*>(source);
  char buf[8];
  // Discards read data.
  while (read(watch->poll_fd.fd, buf, 8) > 0) {}
  watch->unix_server->Render();
  return TRUE;
}
}  // namespace

UnixServer::UnixServer(GtkWrapperInterface *gtk)
    : gtk_(gtk) {
}

UnixServer::~UnixServer() {
}

void UnixServer::AsyncHide() {
  // obsolete callback
}

void UnixServer::AsyncQuit() {
  gtk_->GtkMainQuit();
}

bool UnixServer::Render() {
  string message;
  {
    scoped_lock l(&mutex_);
    message.assign(message_);
  }

  commands::RendererCommand command;
  if (command.ParseFromString(message)) {
    ExecCommandInternal(command);
  } else {
    LOG(WARNING) << "Parse From String Failed";
  }
  return true;
}

bool UnixServer::AsyncExecCommand(string *proto_message) {
  {
    // Take the ownership of |proto_message|.
    unique_ptr<string> proto_message_owner(proto_message);
    scoped_lock l(&mutex_);
    if (message_ == *proto_message_owner.get()) {
      // This is exactly the same to the previous message. Theoretically it is
      // safe to do nothing here.
      return true;
    }
    // Since mozc rendering protocol is state-less, we can always ignore the
    // previous content of |message_|.
    message_.swap(*proto_message_owner.get());
  }

  const char dummy_data = 0;
  if (write(pipefd_[1], &dummy_data, sizeof(dummy_data)) < 0) {
    LOG(ERROR) << "Pipe write failed";
  }
  return true;
}

int UnixServer::StartMessageLoop() {
  GSourceFuncs src_funcs = {
    mozc_prepare,
    mozc_check,
    mozc_dispatch,
    NULL
  };

  MozcWatchSource *watch = reinterpret_cast<MozcWatchSource*>(
      gtk_->GSourceNew(&src_funcs, sizeof(MozcWatchSource)));
  gtk_->GSourceSetCanRecurse(&watch->source, TRUE);
  gtk_->GSourceAttach(&watch->source, NULL);
  gtk_->GSourceSetCallback(&watch->source,
                           NULL,
                           (gpointer)this,
                           NULL);

  watch->poll_fd.fd = pipefd_[0];
  watch->poll_fd.events = G_IO_IN | G_IO_HUP;
  watch->poll_fd.revents = 0;
  watch->unix_server = this;

  gtk_->GSourceAddPoll(reinterpret_cast<GSource*>(watch), &watch->poll_fd);

  gtk_->GdkThreadsEnter();
  gtk_->GtkMain();
  gtk_->GdkThreadsLeave();

  return 0;
}

void UnixServer::OpenPipe() {
  if (pipe(pipefd_) == 1) {
    LOG(FATAL) << "popen failed";
    return;
  }

  // TODO(nona): Close unsued fd.
  fcntl(pipefd_[0], F_SETFL, O_NONBLOCK);
  fcntl(pipefd_[1], F_SETFL, O_NONBLOCK);
}

}  // namespace gtk
}  // namespace renderer
}  // namespace mozc
