// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/shell/platform/windows/win32_window.h"

#include "dpi_utils.h"

namespace flutter {

namespace {
char32_t CodePointFromSurrogatePair(wchar_t high, wchar_t low) {
  return 0x10000 + ((static_cast<char32_t>(high) & 0x000003FF) << 10) +
         (low & 0x3FF);
}
}  // namespace

Win32Window::Win32Window() {
  // Get the DPI of the primary monitor as the initial DPI. If Per-Monitor V2 is
  // supported, |current_dpi_| should be updated in the
  // kWmDpiChangedBeforeParent message.
  current_dpi_ = GetDpiForHWND(nullptr);
}

Win32Window::~Win32Window() {
  Destroy();
}

void Win32Window::InitializeChild(const char* title,
                                  unsigned int width,
                                  unsigned int height) {
  Destroy();
  std::wstring converted_title = NarrowToWide(title);

  WNDCLASS window_class = RegisterWindowClass(converted_title);

  auto* result = CreateWindowEx(
      0, window_class.lpszClassName, converted_title.c_str(),
      WS_CHILD | WS_VISIBLE, CW_DEFAULT, CW_DEFAULT, width, height,
      HWND_MESSAGE, nullptr, window_class.hInstance, this);

  if (result == nullptr) {
    auto error = GetLastError();
    LPWSTR message = nullptr;
    size_t size = FormatMessageW(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        reinterpret_cast<LPWSTR>(&message), 0, NULL);
    OutputDebugString(message);
    LocalFree(message);
  }
}

std::wstring Win32Window::NarrowToWide(const char* source) {
  size_t length = strlen(source);
  size_t outlen = 0;
  std::wstring wideTitle(length, L'#');
  mbstowcs_s(&outlen, &wideTitle[0], length + 1, source, length);
  return wideTitle;
}

WNDCLASS Win32Window::RegisterWindowClass(std::wstring& title) {
  window_class_name_ = title;

  WNDCLASS window_class{};
  window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
  window_class.lpszClassName = title.c_str();
  window_class.style = CS_HREDRAW | CS_VREDRAW;
  window_class.cbClsExtra = 0;
  window_class.cbWndExtra = 0;
  window_class.hInstance = GetModuleHandle(nullptr);
  window_class.hIcon = nullptr;
  window_class.hbrBackground = 0;
  window_class.lpszMenuName = nullptr;
  window_class.lpfnWndProc = WndProc;
  RegisterClass(&window_class);
  return window_class;
}

LRESULT CALLBACK Win32Window::WndProc(HWND const window,
                                      UINT const message,
                                      WPARAM const wparam,
                                      LPARAM const lparam) noexcept {
  if (message == WM_NCCREATE) {
    auto cs = reinterpret_cast<CREATESTRUCT*>(lparam);
    SetWindowLongPtr(window, GWLP_USERDATA,
                     reinterpret_cast<LONG_PTR>(cs->lpCreateParams));

    auto that = static_cast<Win32Window*>(cs->lpCreateParams);
    that->window_handle_ = window;
  } else if (Win32Window* that = GetThisFromHandle(window)) {
    return that->MessageHandler(window, message, wparam, lparam);
  }

  return DefWindowProc(window, message, wparam, lparam);
}

void Win32Window::TrackMouseLeaveEvent(HWND hwnd) {
  if (!tracking_mouse_leave_) {
    TRACKMOUSEEVENT tme;
    tme.cbSize = sizeof(tme);
    tme.hwndTrack = hwnd;
    tme.dwFlags = TME_LEAVE;
    TrackMouseEvent(&tme);
    tracking_mouse_leave_ = true;
  }
}

LRESULT
Win32Window::MessageHandler(HWND hwnd,
                            UINT const message,
                            WPARAM const wparam,
                            LPARAM const lparam) noexcept {
  int xPos = 0, yPos = 0;
  UINT width = 0, height = 0;
  auto window =
      reinterpret_cast<Win32Window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
  UINT button_pressed = 0;

  if (window != nullptr) {
    switch (message) {
      case kWmDpiChangedBeforeParent:
        current_dpi_ = GetDpiForHWND(window_handle_);
        window->OnDpiScale(current_dpi_);
        return 0;
      case WM_SIZE:
        width = LOWORD(lparam);
        height = HIWORD(lparam);

        current_width_ = width;
        current_height_ = height;
        window->HandleResize(width, height);
        break;
      case WM_FONTCHANGE:
        window->OnFontChange();
        break;
      case WM_MOUSEMOVE:
        window->TrackMouseLeaveEvent(hwnd);

        xPos = GET_X_LPARAM(lparam);
        yPos = GET_Y_LPARAM(lparam);
        window->OnPointerMove(static_cast<double>(xPos),
                              static_cast<double>(yPos));
        break;
      case WM_MOUSELEAVE:;
        window->OnPointerLeave();
        // Once the tracked event is received, the TrackMouseEvent function
        // resets. Set to false to make sure it's called once mouse movement is
        // detected again.
        tracking_mouse_leave_ = false;
        break;
      case WM_LBUTTONDOWN:
      case WM_RBUTTONDOWN:
      case WM_MBUTTONDOWN:
      case WM_XBUTTONDOWN:
        if (message == WM_LBUTTONDOWN) {
          // Capture the pointer in case the user drags outside the client area.
          // In this case, the "mouse leave" event is delayed until the user
          // releases the button. It's only activated on left click given that
          // it's more common for apps to handle dragging with only the left
          // button.
          SetCapture(hwnd);
        }
        button_pressed = message;
        if (message == WM_XBUTTONDOWN) {
          button_pressed = GET_XBUTTON_WPARAM(wparam);
        }
        xPos = GET_X_LPARAM(lparam);
        yPos = GET_Y_LPARAM(lparam);
        window->OnPointerDown(static_cast<double>(xPos),
                              static_cast<double>(yPos), button_pressed);
        break;
      case WM_LBUTTONUP:
      case WM_RBUTTONUP:
      case WM_MBUTTONUP:
      case WM_XBUTTONUP:
        if (message == WM_LBUTTONUP) {
          ReleaseCapture();
        }
        button_pressed = message;
        if (message == WM_XBUTTONUP) {
          button_pressed = GET_XBUTTON_WPARAM(wparam);
        }
        xPos = GET_X_LPARAM(lparam);
        yPos = GET_Y_LPARAM(lparam);
        window->OnPointerUp(static_cast<double>(xPos),
                            static_cast<double>(yPos), button_pressed);
        break;
      case WM_MOUSEWHEEL:
        window->OnScroll(
            0.0, -(static_cast<short>(HIWORD(wparam)) / (double)WHEEL_DELTA));
        break;
      case WM_UNICHAR: {
        // Tell third-pary app, we can support Unicode.
        if (wparam == UNICODE_NOCHAR)
          return TRUE;
        // DefWindowProc will send WM_CHAR for this WM_UNICHAR.
        break;
      }
      case WM_DEADCHAR:
      case WM_SYSDEADCHAR:
      case WM_CHAR:
      case WM_SYSCHAR: {
        static wchar_t s_pending_high_surrogate = 0;

        wchar_t character = static_cast<wchar_t>(wparam);
        std::u16string text({character});
        char32_t code_point = character;
        if (IS_HIGH_SURROGATE(character)) {
          // Save to send later with the trailing surrogate.
          s_pending_high_surrogate = character;
        } else if (IS_LOW_SURROGATE(character) &&
                   s_pending_high_surrogate != 0) {
          text.insert(text.begin(), s_pending_high_surrogate);
          // Merge the surrogate pairs for the key event.
          code_point =
              CodePointFromSurrogatePair(s_pending_high_surrogate, character);
          s_pending_high_surrogate = 0;
        }

        // Of the messages handled here, only WM_CHAR should be treated as
        // characters. WM_SYS*CHAR are not part of text input, and WM_DEADCHAR
        // will be incorporated into a later WM_CHAR with the full character.
        // Also filter out:
        // - Lead surrogates, which like dead keys will be send once combined.
        // - ASCII control characters, which are sent as WM_CHAR events for all
        //   control key shortcuts.
        if (message == WM_CHAR && s_pending_high_surrogate == 0 &&
            character >= u' ') {
          window->OnText(text);
        }

        // All key presses that generate a character should be sent from
        // WM_CHAR. In order to send the full key press information, the keycode
        // is persisted in keycode_for_char_message_ obtained from WM_KEYDOWN.
        if (keycode_for_char_message_ != 0) {
          const unsigned int scancode = (lparam >> 16) & 0xff;
          window->OnKey(keycode_for_char_message_, scancode, WM_KEYDOWN,
                        code_point);
          keycode_for_char_message_ = 0;
        }
        break;
      }
      case WM_KEYDOWN:
      case WM_SYSKEYDOWN:
      case WM_KEYUP:
      case WM_SYSKEYUP:
        const bool is_keydown_message =
            (message == WM_KEYDOWN || message == WM_SYSKEYDOWN);
        // Check if this key produces a character. If so, the key press should
        // be sent with the character produced at WM_CHAR. Store the produced
        // keycode (it's not accessible from WM_CHAR) to be used in WM_CHAR.
        const unsigned int character = MapVirtualKey(wparam, MAPVK_VK_TO_CHAR);
        if (character > 0 && is_keydown_message) {
          keycode_for_char_message_ = wparam;
          break;
        }
        unsigned int keyCode(wparam);
        const unsigned int scancode = (lparam >> 16) & 0xff;
        // If the key is a modifier, get its side.
        if (keyCode == VK_SHIFT || keyCode == VK_MENU ||
            keyCode == VK_CONTROL) {
          keyCode = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX);
        }
        const int action = is_keydown_message ? WM_KEYDOWN : WM_KEYUP;
        window->OnKey(keyCode, scancode, action, 0);
        break;
    }
    return DefWindowProc(hwnd, message, wparam, lparam);
  }

  return DefWindowProc(window_handle_, message, wparam, lparam);
}

UINT Win32Window::GetCurrentDPI() {
  return current_dpi_;
}

UINT Win32Window::GetCurrentWidth() {
  return current_width_;
}

UINT Win32Window::GetCurrentHeight() {
  return current_height_;
}

HWND Win32Window::GetWindowHandle() {
  return window_handle_;
}

void Win32Window::Destroy() {
  if (window_handle_) {
    DestroyWindow(window_handle_);
    window_handle_ = nullptr;
  }

  UnregisterClass(window_class_name_.c_str(), nullptr);
}

void Win32Window::HandleResize(UINT width, UINT height) {
  current_width_ = width;
  current_height_ = height;
  OnResize(width, height);
}

Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
  return reinterpret_cast<Win32Window*>(
      GetWindowLongPtr(window, GWLP_USERDATA));
}

}  // namespace flutter
