// Copyright 2016 Samsung Electronics. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/shared/wayland/application_wayland.h"

#include <EGL/egl.h>
#include <poll.h>
#include <sys/eventfd.h>

#include "starboard/log.h"
#include "starboard/memory.h"
#include "starboard/shared/wayland/dev_input.h"
#include "starboard/shared/wayland/window_internal.h"
#include "starboard/time.h"

// YouTube Technical Requirement 2018 (2016/11/1 - Initial draft)
// 9.5 The device MUST dispatch the following key events, as appropriate:
//  * Window.keydown
//      * After a key is held down for 500ms, the Window.keydown event
//        MUST repeat every 50ms until a user stops holding the key down.
//  * Window.keyup
static const SbTime kKeyHoldTime = 500 * kSbTimeMillisecond;
static const SbTime kKeyRepeatTime = 50 * kSbTimeMillisecond;

namespace starboard {
namespace shared {
namespace wayland {

// Tizen application engine using the generic queue and a tizen implementation.

ApplicationWayland::ApplicationWayland(float video_pixel_ratio)
    : video_pixel_ratio_(video_pixel_ratio),
      seat_(NULL),
      keyboard_(NULL),
      key_repeat_event_id_(kSbEventIdInvalid),
      key_repeat_interval_(kKeyHoldTime),
      key_modifiers_(0) {}

SbWindow ApplicationWayland::CreateWindow(const SbWindowOptions* options) {
  SB_DLOG(INFO) << "CreateWindow";
  SbWindow window = new SbWindowPrivate(options, video_pixel_ratio_);
  window_ = window;

// Video Plane
#if SB_CAN(USE_WAYLAND_VIDEO_WINDOW)
  window->video_window = display_;
#else
  window->video_window = elm_win_add(NULL, "Cobalt_Video", ELM_WIN_BASIC);
  elm_win_title_set(window->video_window, "Cobalt_Video");
  elm_win_autodel_set(window->video_window, EINA_TRUE);
  evas_object_resize(window->video_window, window->width, window->height);
  evas_object_hide(window->video_window);
#endif

  // Graphics Plane
  window->surface = wl_compositor_create_surface(compositor_);
  window->shell_surface = wl_shell_get_shell_surface(shell_, window->surface);
  wl_shell_surface_add_listener(window->shell_surface, &shell_surface_listener,
                                window);

  window->tz_visibility =
      tizen_policy_get_visibility(tz_policy_, window->surface);
  tizen_visibility_add_listener(window->tz_visibility,
                                &tizen_visibility_listener, window);
  tizen_policy_activate(tz_policy_, window->surface);
  wl_shell_surface_set_title(window->shell_surface, "cobalt");
  WindowRaise();

  struct wl_region* region;
  region = wl_compositor_create_region(compositor_);
  wl_region_add(region, 0, 0, window->width, window->height);
  wl_surface_set_opaque_region(window->surface, region);
  wl_region_destroy(region);

  window->egl_window =
      wl_egl_window_create(window->surface, window->width, window->height);

  return window;
}

bool ApplicationWayland::DestroyWindow(SbWindow window) {
  SB_DLOG(INFO) << "DestroyWindow";
  if (!SbWindowIsValid(window)) {
    SB_DLOG(WARNING) << "wayland window destroy failed!!";
    return false;
  }

// Video Plane
#if !SB_CAN(USE_WAYLAND_VIDEO_WINDOW)
  evas_object_hide(window->video_window);
#endif
  window->video_window = NULL;

  // Graphics Plane
  tizen_visibility_destroy(window->tz_visibility);
  wl_egl_window_destroy(window->egl_window);
  wl_shell_surface_destroy(window->shell_surface);
  wl_surface_destroy(window->surface);

  return true;
}

void ApplicationWayland::Initialize() {
  SB_DLOG(INFO) << "Initialize";
  // Video Plane
  elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);

  // Graphics Plane
  display_ = wl_display_connect(NULL);
  struct wl_registry* registry = wl_display_get_registry(display_);
  wl_registry_add_listener(registry, &registry_listener, this);
  wl_display_dispatch(display_);
  wl_display_roundtrip(display_);

  // Open wakeup event
  wakeup_fd_ = eventfd(0, 0);
  if (wakeup_fd_ == -1)
    SB_DLOG(ERROR) << "wakeup_fd_ creation failed";

  InitializeEgl();
}

void ApplicationWayland::Teardown() {
  SB_DLOG(INFO) << "Teardown";
  DeleteRepeatKey();

  TerminateEgl();

  wl_display_flush(display_);
  wl_display_disconnect(display_);

  // Close wakeup event
  close(wakeup_fd_);
}

void ApplicationWayland::OnSuspend() {
  TerminateEgl();
}

void ApplicationWayland::OnResume() {
  InitializeEgl();
}

void ApplicationWayland::InitializeEgl() {
  EGLDisplay egl_display = eglGetDisplay(display_);
  SB_DLOG(INFO) << __FUNCTION__ << ": INITIALIZE egl_display=" << egl_display;
  SB_DCHECK(egl_display);
  eglInitialize(egl_display, NULL, NULL);
}

void ApplicationWayland::TerminateEgl() {
  EGLDisplay egl_display = eglGetDisplay(display_);
  SB_DLOG(INFO) << __FUNCTION__ << ": TERMINATE egl_display=" << egl_display;
  SB_DCHECK(egl_display);
  eglTerminate(egl_display);
}

bool ApplicationWayland::MayHaveSystemEvents() {
  // SB_DCHECK(SbThreadIsValid(wayland_thread_));
  return display_;
}

shared::starboard::Application::Event*
ApplicationWayland::PollNextSystemEvent() {
  // if queue is empty, try to read fd and push event to queue
  if (wl_display_prepare_read(display_) == 0) {
    wl_display_read_events(display_);
  }

  // dispatch queue if any event
  if (wl_display_dispatch_pending(display_) < 0) {
    SB_DLOG(ERROR) << "wl_display_dispatch_pending Error";
    return NULL;
  }

  return NULL;
}

shared::starboard::Application::Event*
ApplicationWayland::WaitForSystemEventWithTimeout(SbTime duration) {
  if (wl_display_flush(display_) < 0) {
    SB_DLOG(ERROR) << "wl_display_flush Error";
    return NULL;
  }

  struct pollfd fds[2];
  struct timespec timeout_ts;
  int ret;

  timeout_ts.tv_sec = duration / kSbTimeSecond;
  timeout_ts.tv_nsec =
      (duration % kSbTimeSecond) * kSbTimeNanosecondsPerMicrosecond;

  // wait wayland event
  fds[0].fd = wl_display_get_fd(display_);
  fds[0].events = POLLIN;
  fds[0].revents = 0;

  // wait wakeup event by event injection
  fds[1].fd = wakeup_fd_;
  fds[1].events = POLLIN;
  fds[1].revents = 0;

  ret = ppoll(fds, 2, &timeout_ts, NULL);

  if (timeout_ts.tv_sec > 0)  // long-wait log
    SB_DLOG(INFO) << "WaitForSystemEventWithTimeout : wakeup " << ret << " 0("
                  << fds[0].revents << ") 1(" << fds[1].revents << ")";

  if (ret > 0 && fds[1].revents & POLLIN) {  // clear wakeup event
    uint64_t u;
    read(wakeup_fd_, &u, sizeof(uint64_t));
  }

  // TODO : print log for too short waiting(under 2ms) to prevent abnormal fd
  // events.

  return NULL;
}

void ApplicationWayland::WakeSystemEventWait() {
  uint64_t u = 1;
  write(wakeup_fd_, &u, sizeof(uint64_t));
}

void ApplicationWayland::CreateRepeatKey() {
  if (!key_repeat_state_) {
    return;
  }

  if (key_repeat_interval_) {
    key_repeat_interval_ = kKeyRepeatTime;
  }

  CreateKey(key_repeat_key_, key_repeat_state_, true);
}

void ApplicationWayland::DeleteRepeatKey() {
  if (key_repeat_event_id_ != kSbEventIdInvalid) {
    SbEventCancel(key_repeat_event_id_);
    key_repeat_event_id_ = kSbEventIdInvalid;
  }
}

void ApplicationWayland::CreateKey(int key, int state, bool is_repeat) {
  SbInputData* data = new SbInputData();
  SbMemorySet(data, 0, sizeof(*data));
  data->window = window_;
  data->type = (state == 0 ? kSbInputEventTypeUnpress : kSbInputEventTypePress);
  data->device_type = kSbInputDeviceTypeRemote;
  data->device_id = 1;                           // kKeyboardDeviceId;
  data->key = KeyCodeToSbKey(key);
  data->key_location = KeyCodeToSbKeyLocation(key);
  data->key_modifiers = key_modifiers_;
  Inject(new Event(kSbEventTypeInput, data,
                   &Application::DeleteDestructor<SbInputData>));

  DeleteRepeatKey();

  if (is_repeat && state) {
    key_repeat_key_ = key;
    key_repeat_state_ = state;
    key_repeat_event_id_ = SbEventSchedule([](void* window) {
      ApplicationWayland* application =
          reinterpret_cast<ApplicationWayland*>(window);
      application->CreateRepeatKey();
    }, this, key_repeat_interval_);
  } else {
    key_repeat_interval_ = kKeyHoldTime;
  }
}

void ApplicationWayland::WindowRaise() {
  if (tz_policy_)
    tizen_policy_raise(tz_policy_, window_->surface);
  if (window_->shell_surface)
    wl_shell_surface_set_toplevel(window_->shell_surface);
}

void ApplicationWayland::Pause(void* context, EventHandledCallback callback) {
  Application::Pause(context, callback);

  ScopedLock lock(observers_mutex_);
  std::for_each(observers_.begin(), observers_.end(),
                [](StateObserver* i) { i->OnAppPause(); });
}

void ApplicationWayland::Unpause(void* context, EventHandledCallback callback) {
  Application::Unpause(context, callback);

  ScopedLock lock(observers_mutex_);
  std::for_each(observers_.begin(), observers_.end(),
                [](StateObserver* i) { i->OnAppUnpause(); });
}

void ApplicationWayland::RegisterObserver(StateObserver* observer) {
  ScopedLock lock(observers_mutex_);
  observers_.push_back(observer);
}

void ApplicationWayland::UnregisterObserver(StateObserver* observer) {
  ScopedLock lock(observers_mutex_);
  auto it = std::find_if(
      observers_.begin(), observers_.end(),
      [observer](const StateObserver* i) { return observer == i; });
  if (it == observers_.end())
    return;
  observers_.erase(it);
}

void ApplicationWayland::Deeplink(char* payload) {
  const size_t payload_size = strlen(payload) + 1;
  char* copied_payload = new char[payload_size];
  snprintf(copied_payload, payload_size, "%s", payload);
  Inject(new Event(kSbEventTypeLink, copiedPayload,
                   [](void* data) { delete[] reinterpret_cast<char*>(data); }));
}

}  // namespace wayland
}  // namespace shared
}  // namespace starboard
