// Copyright 2017 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 "starboard/shared/win32/application_win32.h"

#include <windows.h>  // NOLINT(build/include_order)

#include <cstdio>
#include <string>

#include "starboard/shared/starboard/application.h"
#include "starboard/shared/win32/dialog.h"
#include "starboard/shared/win32/error_utils.h"
#include "starboard/shared/win32/thread_private.h"
#include "starboard/shared/win32/wchar_utils.h"
#include "starboard/shared/win32/window_internal.h"

using starboard::shared::starboard::Application;
using starboard::shared::win32::ApplicationWin32;
using starboard::shared::win32::CStringToWString;
using starboard::shared::win32::DebugLogWinError;

namespace {

static const TCHAR kWindowClassName[] = L"window_class_name";

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM w_param, LPARAM l_param) {
  return ApplicationWin32::Get()->WindowProcess(hWnd, msg, w_param, l_param);
}

bool RegisterWindowClass() {
  WNDCLASSEX window_class;
  window_class.cbSize = sizeof(WNDCLASSEX);
  // https://msdn.microsoft.com/en-us/library/windows/desktop/ff729176(v=vs.85).aspx
  window_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  window_class.lpfnWndProc = WndProc;
  window_class.cbClsExtra = 0;
  window_class.cbWndExtra = 0;
  window_class.hInstance = GetModuleHandle(nullptr);
  // TODO: Add YouTube icon.
  window_class.hIcon = LoadIcon(window_class.hInstance, IDI_APPLICATION);
  window_class.hIconSm = LoadIcon(window_class.hInstance, IDI_APPLICATION);
  window_class.hCursor = LoadCursor(NULL, IDC_ARROW);
  window_class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  window_class.lpszMenuName = NULL;
  window_class.lpszClassName = kWindowClassName;

  if (!::RegisterClassEx(&window_class)) {
    SB_LOG(ERROR) << "Failed to register window";
    DebugLogWinError();
    return false;
  }
  return true;
}

// Create a Windows window.
HWND CreateWindowInstance(const SbWindowOptions& options) {
  DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_CLIPSIBLINGS |
                  WS_CLIPCHILDREN | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
  if (options.windowed) {
    dwStyle |= WS_MAXIMIZE;
  }
  const std::wstring wide_window_name = CStringToWString(options.name);
  const HWND window = CreateWindow(
      kWindowClassName, wide_window_name.c_str(), dwStyle, CW_USEDEFAULT,
      CW_USEDEFAULT, options.size.width, options.size.height, nullptr, nullptr,
      GetModuleHandle(nullptr), nullptr);
  SetForegroundWindow(window);
  if (window == nullptr) {
    SB_LOG(ERROR) << "Failed to create window.";
    DebugLogWinError();
  }

  return window;
}

}  // namespace

// Note that this is a "struct" and not a "class" because
// that's how it's defined in starboard/system.h
struct SbSystemPlatformErrorPrivate {
  SbSystemPlatformErrorPrivate(const SbSystemPlatformErrorPrivate&) = delete;
  SbSystemPlatformErrorPrivate& operator=(const SbSystemPlatformErrorPrivate&) =
      delete;

  SbSystemPlatformErrorPrivate(SbSystemPlatformErrorType type,
                               SbSystemPlatformErrorCallback callback,
                               void* user_data)
      : callback_(callback), user_data_(user_data) {
    if (type != kSbSystemPlatformErrorTypeConnectionError)
      SB_NOTREACHED();

    ApplicationWin32* app = ApplicationWin32::Get();
    const bool created_dialog = starboard::shared::win32::ShowOkCancelDialog(
        app->GetCoreWindow()->GetWindowHandle(),
        "",  // No title.
        app->GetLocalizedString("UNABLE_TO_CONTACT_YOUTUBE_1",
                                "Sorry, could not connect to YouTube."),
        app->GetLocalizedString("RETRY_BUTTON", "Retry"),
        [this, callback, user_data]() {
          callback(kSbSystemPlatformErrorResponsePositive, user_data);
        },
        app->GetLocalizedString("EXIT_BUTTON", "Exit"),
        [this, callback, user_data]() {
          callback(kSbSystemPlatformErrorResponseNegative, user_data);
        });
    SB_DCHECK(!created_dialog);
    if (!created_dialog) {
      SB_LOG(ERROR) << "Failed to create dialog!";
    }
  }

  void Clear() { starboard::shared::win32::CancelDialog(); }

 private:
  SbSystemPlatformErrorCallback callback_;
  void* user_data_;
};

namespace starboard {
namespace shared {
namespace win32 {

ApplicationWin32::ApplicationWin32()
    : localized_strings_(SbSystemGetLocaleId()) {}
ApplicationWin32::~ApplicationWin32() {}

SbWindow ApplicationWin32::CreateWindowForWin32(
    const SbWindowOptions* options) {
  if (SbWindowIsValid(window_.get())) {
    SB_LOG(WARNING) << "Returning existing window instance.";
    return window_.get();
  }

  RegisterWindowClass();
  HWND window;
  if (options) {
    window = CreateWindowInstance(*options);
    window_.reset(new SbWindowPrivate(options, window));
  } else {
    SbWindowOptions default_options;
    SbWindowSetDefaultOptions(&default_options);
    window = CreateWindowInstance(default_options);
    window_.reset(new SbWindowPrivate(&default_options, window));
  }
  ShowWindow(window, SW_SHOW);
  UpdateWindow(window);
  return window_.get();
}

bool ApplicationWin32::DestroyWindow(SbWindow window) {
  if (!SbWindowIsValid(window) || window != window_.get()) {
    return false;
  }
  window_.reset();
  return true;
}

SbSystemPlatformError ApplicationWin32::OnSbSystemRaisePlatformError(
    SbSystemPlatformErrorType type,
    SbSystemPlatformErrorCallback callback,
    void* user_data) {
  return new SbSystemPlatformErrorPrivate(type, callback, user_data);
}

void ApplicationWin32::OnSbSystemClearPlatformError(
    SbSystemPlatformError handle) {
  if (handle == kSbSystemPlatformErrorInvalid) {
    return;
  }
  static_cast<SbSystemPlatformErrorPrivate*>(handle)->Clear();
  // TODO: Determine if this should actually be deleted and if so, delete or
  // don't consistently across platforms.
  delete handle;
}

Application::Event* ApplicationWin32::WaitForSystemEventWithTimeout(
    SbTime time) {
  ProcessNextSystemMessage();
  if (pending_event_) {
    Event* out = pending_event_;
    pending_event_ = nullptr;
    return out;
  }

  ScopedLock lock(stop_waiting_for_system_events_mutex_);
  if (time <= SbTimeGetMonotonicNow() || stop_waiting_for_system_events_) {
    stop_waiting_for_system_events_ = false;
    return nullptr;
  }

  return WaitForSystemEventWithTimeout(time);
}

LRESULT ApplicationWin32::WindowProcess(HWND hWnd,
                                        UINT msg,
                                        WPARAM w_param,
                                        LPARAM l_param) {
  switch (msg) {
    // Input message handling.
    case WM_KEYDOWN:
    case WM_SYSKEYDOWN:
    case WM_KEYUP:
    case WM_SYSKEYUP:
      // TODO: Listen for mouse events as well.
      pending_event_ =
          ProcessWinKeyEvent(GetCoreWindow(), msg, w_param, l_param);
      break;
    case WM_DESTROY:
      SB_LOG(INFO) << "Received destroy message; exiting.";
      PostQuitMessage(0);
      break;
    default:
      return DefWindowProcW(hWnd, msg, w_param, l_param);
  }
  return 0;
}

bool ApplicationWin32::ProcessNextSystemMessage() {
  MSG msg;
  BOOL get_message_return = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
  if (get_message_return == -1) {
    SB_LOG(INFO) << "Error while getting messages";
    return false;
  }
  if (!DialogHandleMessage(&msg)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  if (get_message_return == 0) {
    return false;
  }
  return true;
}

}  // namespace win32
}  // namespace shared
}  // namespace starboard
