/*
 * 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);
}

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
