/*
 * Copyright 2015 Google Inc. 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 "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/stringprintf.h"
#include "cobalt/base/event_dispatcher.h"
#include "cobalt/deprecated/platform_delegate.h"
#include "cobalt/system_window/keyboard_event.h"
#include "cobalt/system_window/starboard/system_window.h"
#include "starboard/system.h"

namespace cobalt {
namespace system_window {

namespace {

SystemWindowStarboard* g_the_window = NULL;

// Unbound callback handler for SbWindowShowDialog.
void StarboardDialogCallback(SbSystemPlatformErrorResponse response) {
  DCHECK(g_the_window);
  g_the_window->HandleDialogClose(response);
}

void UpdateVideoContainerSizeOverride(SbWindow window) {
  SbWindowSize window_size;
  if (!SbWindowGetSize(window, &window_size)) {
    DLOG(WARNING) << "SbWindowGetSize() failed.";
    return;
  }
  if (window_size.video_pixel_ratio == 1.0f) {
    return;
  }

  deprecated::PlatformDelegate::Get()->SetVideoContainerSizeOverride(
      base::StringPrintf(
          "%dx%d",
          static_cast<int>(window_size.width * window_size.video_pixel_ratio),
          static_cast<int>(window_size.height *
                           window_size.video_pixel_ratio)));
}

}  // namespace

SystemWindowStarboard::SystemWindowStarboard(
    base::EventDispatcher* event_dispatcher)
    : SystemWindow(event_dispatcher),
      window_(kSbWindowInvalid),
      key_down_(false) {
  window_ = SbWindowCreate(NULL);
  DCHECK(SbWindowIsValid(window_));
  DCHECK(!g_the_window) << "TODO: Support multiple SystemWindows.";
  UpdateVideoContainerSizeOverride(window_);
  g_the_window = this;
}

SystemWindowStarboard::SystemWindowStarboard(
    base::EventDispatcher* event_dispatcher, const math::Size& window_size)
    : SystemWindow(event_dispatcher),
      window_(kSbWindowInvalid),
      key_down_(false) {
  SbWindowOptions options;
  SbWindowSetDefaultOptions(&options);
  options.size.width = window_size.width();
  options.size.height = window_size.height();
  window_ = SbWindowCreate(&options);
  DCHECK(SbWindowIsValid(window_));
  DCHECK(!g_the_window) << "TODO: Support multiple SystemWindows.";
  UpdateVideoContainerSizeOverride(window_);
  g_the_window = this;
}

SystemWindowStarboard::~SystemWindowStarboard() {
  DCHECK_EQ(this, g_the_window);

  if (g_the_window == this) {
    deprecated::PlatformDelegate::Get()->SetVideoContainerSizeOverride("");
    g_the_window = NULL;
  }
  SbWindowDestroy(window_);
}

math::Size SystemWindowStarboard::GetWindowSize() const {
  SbWindowSize window_size;
  if (!SbWindowGetSize(window_, &window_size)) {
    DLOG(WARNING) << "SbWindowGetSize() failed.";
    return math::Size(0, 0);
  }
  return math::Size(window_size.width, window_size.height);
}

float SystemWindowStarboard::GetVideoPixelRatio() const {
  SbWindowSize window_size;
  if (!SbWindowGetSize(window_, &window_size)) {
    DLOG(WARNING) << "SbWindowGetSize() failed.";
    return 1.0;
  }
  return window_size.video_pixel_ratio;
}

SbWindow SystemWindowStarboard::GetSbWindow() { return window_; }

void* SystemWindowStarboard::GetWindowHandle() {
  return SbWindowGetPlatformHandle(window_);
}

void SystemWindowStarboard::HandleInputEvent(const SbInputData& data) {
  DCHECK_EQ(window_, data.window);

  if (data.type == kSbInputEventTypePress) {
    // Starboard handily uses the Microsoft key mapping, which is also what
    // Cobalt uses.
    int key_code = static_cast<int>(data.key);
    scoped_ptr<KeyboardEvent> keyboard_event(
        new KeyboardEvent(KeyboardEvent::kKeyDown, key_code, data.key_modifiers,
                          key_down_ /* is_repeat */));
    key_down_ = true;
    event_dispatcher()->DispatchEvent(keyboard_event.PassAs<base::Event>());
  } else if (data.type == kSbInputEventTypeUnpress) {
    key_down_ = false;
    int key_code = static_cast<int>(data.key);
    scoped_ptr<KeyboardEvent> keyboard_event(
        new KeyboardEvent(KeyboardEvent::kKeyUp, key_code, data.key_modifiers,
                          false /* is_repeat */));
    event_dispatcher()->DispatchEvent(keyboard_event.PassAs<base::Event>());
  }
}

void OnDialogClose(SbSystemPlatformErrorResponse response, void* user_data) {
  DCHECK(user_data);
  SystemWindowStarboard* system_window =
      static_cast<SystemWindowStarboard*>(user_data);
  system_window->HandleDialogClose(response);
}

void SystemWindowStarboard::ShowDialog(
    const SystemWindow::DialogOptions& options) {
  SbSystemPlatformErrorType error_type;
  switch (options.message_code) {
    case kDialogConnectionError:
      error_type = kSbSystemPlatformErrorTypeConnectionError;
      break;
    case kDialogUserSignedOut:
      error_type = kSbSystemPlatformErrorTypeUserSignedOut;
      break;
    case kDialogUserAgeRestricted:
      error_type = kSbSystemPlatformErrorTypeUserAgeRestricted;
      break;
    default:
      NOTREACHED();
      break;
  }

  SbSystemPlatformError handle =
      SbSystemRaisePlatformError(error_type, OnDialogClose, this);
  if (SbSystemPlatformErrorIsValid(handle)) {
    current_dialog_callback_ = options.callback;
  } else {
    DLOG(WARNING) << "Failed to notify user of error: "
                  << options.message_code;
  }
}

void SystemWindowStarboard::HandleDialogClose(
    SbSystemPlatformErrorResponse response) {
  DCHECK(!current_dialog_callback_.is_null());
  switch (response) {
    case kSbSystemPlatformErrorResponsePositive:
      current_dialog_callback_.Run(kDialogPositiveResponse);
      break;
    case kSbSystemPlatformErrorResponseNegative:
      current_dialog_callback_.Run(kDialogNegativeResponse);
      break;
    case kSbSystemPlatformErrorResponseCancel:
      current_dialog_callback_.Run(kDialogCancelResponse);
      break;
    default:
      DLOG(WARNING) << "Unrecognized dialog response: " << response;
      break;
  }
}

scoped_ptr<SystemWindow> CreateSystemWindow(
    base::EventDispatcher* event_dispatcher,
    const base::optional<math::Size>& window_size) {
  if (window_size) {
    return scoped_ptr<SystemWindow>(
        new SystemWindowStarboard(event_dispatcher, *window_size));
  } else {
    return scoped_ptr<SystemWindow>(
        new SystemWindowStarboard(event_dispatcher));
  }
}

// Returns true if the event was handled.
void HandleInputEvent(const SbEvent* event) {
  if (event->type != kSbEventTypeInput) {
    return;
  }

  DCHECK(g_the_window);
  DCHECK(event->data);
  SbInputData* data = reinterpret_cast<SbInputData*>(event->data);
  g_the_window->HandleInputEvent(*data);
  return;
}

}  // namespace system_window
}  // namespace cobalt
