// Copyright (c) 2012 The Chromium 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 <stddef.h>
#include <windows.h>

#include <cstdlib>
#include <memory>

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/win/current_module.h"
#include "base/win/scoped_gdi_object.h"
#include "base/win/scoped_hdc.h"
#include "base/win/scoped_select_object.h"
#include "remoting/host/client_session_control.h"
#include "remoting/host/host_window.h"
#include "remoting/host/input_monitor/local_input_monitor.h"
#include "remoting/host/win/core_resource.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "ui/events/event.h"

namespace remoting {

namespace {

constexpr int DISCONNECT_HOTKEY_ID = 1000;

// Maximum length of "Your desktop is shared with ..." message in UTF-16
// characters.
constexpr size_t kMaxSharingWithTextLength = 100;

constexpr wchar_t kShellTrayWindowName[] = L"Shell_TrayWnd";
constexpr int kWindowBorderRadius = 14;

// Margin between dialog controls (in dialog units).
constexpr int kWindowTextMargin = 8;

// The amount of time to wait before hiding the disconnect window.
constexpr base::TimeDelta kAutoHideTimeout = base::TimeDelta::FromSeconds(10);

// The length of the hide and show animations.
constexpr DWORD kAnimationDurationMs = 200;

class DisconnectWindowWin : public HostWindow {
 public:
  DisconnectWindowWin();
  ~DisconnectWindowWin() override;

  // Allow dialog to auto-hide after a period of time.  The dialog will be
  // reshown when local user input is detected.
  void EnableAutoHide(std::unique_ptr<LocalInputMonitor> local_input_monitor);

  // HostWindow overrides.
  void Start(
      const base::WeakPtr<ClientSessionControl>& client_session_control)
      override;

 private:
  static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT message, WPARAM wparam,
                                     LPARAM lparam);

  BOOL OnDialogMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

  // Creates the dialog window and registers the disconnect hot key.
  bool BeginDialog();

  // Closes the dialog, unregisters the hot key and invokes the disconnect
  // callback, if set.
  void EndDialog();

  // Returns |control| rectangle in the dialog coordinates.
  bool GetControlRect(HWND control, RECT* rect);

  // Positions the dialog window based on the current auto-hide state.
  // If auto-hide is enabled, the window is displayed near the center of the
  // display, otherwise it is displayed just above the taskbar.
  void SetDialogPosition();

  // Applies localization string and resizes the dialog.
  bool SetStrings();

  // Draws the border around the dialog window.  Can be used to draw the initial
  // border or to redraw if when the dialog is reshown.  |hwnd| is the window to
  // have the border applied.  |hdc| is the device context to draw to.
  void DrawBorder(HWND hwnd, HDC hdc);

  // Shows a previously hidden dialog using an animation.
  void ShowDialog();

  // Hides the dialog using an animation.
  void HideDialog();

  // Prevent the dialog from being hidden if local input monitoring fails.
  void StopAutoHideBehavior();

  // Called when local mouse event is seen and shows the dialog (if hidden).
  void OnLocalMouseEvent(const webrtc::DesktopVector& mouse_position,
                         ui::EventType type);

  // Called when local keyboard event is seen and shows the dialog (if hidden).
  void OnLocalKeyboardEvent();

  // Used to disconnect the client session.
  base::WeakPtr<ClientSessionControl> client_session_control_;

  // Used to watch for local input which will trigger the dialog to be reshown.
  std::unique_ptr<LocalInputMonitor> local_input_monitor_;

  // Specifies the remote user name.
  std::string username_;

  bool was_auto_hidden_ = false;
  bool local_input_seen_ = false;
  base::OneShotTimer auto_hide_timer_;

  HWND hwnd_ = nullptr;
  bool has_hotkey_ = false;
  base::win::ScopedGDIObject<HPEN> border_pen_;

  webrtc::DesktopVector mouse_position_;

  base::WeakPtrFactory<DisconnectWindowWin> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(DisconnectWindowWin);
};

// Returns the text for the given dialog control window.
bool GetControlText(HWND control, base::string16* text) {
  // GetWindowText truncates the text if it is longer than can fit into
  // the buffer.
  WCHAR buffer[256];
  int result = GetWindowText(control, buffer, base::size(buffer));
  if (!result)
    return false;

  text->assign(buffer);
  return true;
}

// Returns width |text| rendered in |control| window.
bool GetControlTextWidth(HWND control,
                         const base::string16& text,
                         LONG* width) {
  RECT rect = {0, 0, 0, 0};
  base::win::ScopedGetDC dc(control);
  base::win::ScopedSelectObject font(
      dc, (HFONT)SendMessage(control, WM_GETFONT, 0, 0));
  if (!DrawText(dc, text.c_str(), -1, &rect, DT_CALCRECT | DT_SINGLELINE))
    return false;

  *width = rect.right;
  return true;
}

DisconnectWindowWin::DisconnectWindowWin()
    : border_pen_(
          CreatePen(PS_SOLID, 5, RGB(0.13 * 255, 0.69 * 255, 0.11 * 255))),
      weak_factory_(this) {}

DisconnectWindowWin::~DisconnectWindowWin() {
  EndDialog();
}

void DisconnectWindowWin::EnableAutoHide(
    std::unique_ptr<LocalInputMonitor> local_input_monitor) {
  local_input_monitor_ = std::move(local_input_monitor);
}

void DisconnectWindowWin::Start(
    const base::WeakPtr<ClientSessionControl>& client_session_control) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!client_session_control_);
  DCHECK(client_session_control);

  client_session_control_ = client_session_control;

  std::string client_jid = client_session_control_->client_jid();
  username_ = client_jid.substr(0, client_jid.find('/'));
  if (!BeginDialog()) {
    EndDialog();
    return;
  }

  if (local_input_monitor_) {
    local_input_monitor_->StartMonitoring(
        base::BindRepeating(&DisconnectWindowWin::OnLocalMouseEvent,
                            weak_factory_.GetWeakPtr()),
        base::BindRepeating(&DisconnectWindowWin::OnLocalKeyboardEvent,
                            weak_factory_.GetWeakPtr()),
        base::BindRepeating(&DisconnectWindowWin::StopAutoHideBehavior,
                            weak_factory_.GetWeakPtr()));

    auto_hide_timer_.Start(FROM_HERE, kAutoHideTimeout,
                           base::BindOnce(&DisconnectWindowWin::HideDialog,
                                          base::Unretained(this)));
  }
}

INT_PTR CALLBACK DisconnectWindowWin::DialogProc(HWND hwnd,
                                                 UINT message,
                                                 WPARAM wparam,
                                                 LPARAM lparam) {
  LONG_PTR self = 0;
  if (message == WM_INITDIALOG) {
    self = lparam;

    // Store |this| to the window's user data.
    SetLastError(ERROR_SUCCESS);
    LONG_PTR result = SetWindowLongPtr(hwnd, DWLP_USER, self);
    if (result == 0 && GetLastError() != ERROR_SUCCESS)
      reinterpret_cast<DisconnectWindowWin*>(self)->EndDialog();
  } else {
    self = GetWindowLongPtr(hwnd, DWLP_USER);
  }

  if (self) {
    return reinterpret_cast<DisconnectWindowWin*>(self)->OnDialogMessage(
        hwnd, message, wparam, lparam);
  }
  return FALSE;
}

BOOL DisconnectWindowWin::OnDialogMessage(HWND hwnd,
                                          UINT message,
                                          WPARAM wparam,
                                          LPARAM lparam) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  switch (message) {
    // Ignore close messages.
    case WM_CLOSE:
      return TRUE;

    // Handle the Disconnect button.
    case WM_COMMAND:
      switch (LOWORD(wparam)) {
        case IDC_DISCONNECT:
          EndDialog();
          return TRUE;
      }
      return FALSE;

    // Ensure we don't try to use the HWND anymore.
    case WM_DESTROY:
      hwnd_ = nullptr;

      // Ensure that the disconnect callback is invoked even if somehow our
      // window gets destroyed.
      EndDialog();

      return TRUE;

    // Ensure the dialog stays visible if the work area dimensions change.
    case WM_SETTINGCHANGE:
      if (wparam == SPI_SETWORKAREA)
        SetDialogPosition();
      return TRUE;

    // Ensure the dialog stays visible if the display dimensions change.
    case WM_DISPLAYCHANGE:
      SetDialogPosition();
      return TRUE;

    // Handle the disconnect hot-key.
    case WM_HOTKEY:
      EndDialog();
      return TRUE;

    // Let the window be draggable by its client area by responding
    // that the entire window is the title bar.
    case WM_NCHITTEST:
      SetWindowLongPtr(hwnd, DWLP_MSGRESULT, HTCAPTION);
      return TRUE;

    case WM_PAINT: {
      // Draw the client area after ShowWindow is used to make |hwnd_| visible.
      PAINTSTRUCT ps;
      HDC hdc = BeginPaint(hwnd_, &ps);
      DrawBorder(hwnd_, hdc);
      EndPaint(hwnd_, &ps);
      return TRUE;
    }

    case WM_PRINTCLIENT: {
      // Refresh the dialog client area.  Called after AnimateWindow is used to
      // reshow the dialog.
      HDC hdc = reinterpret_cast<HDC>(wparam);
      DrawBorder(hwnd_, hdc);
      return TRUE;
    }
  }
  return FALSE;
}

bool DisconnectWindowWin::BeginDialog() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!hwnd_);

  hwnd_ =
      CreateDialogParam(CURRENT_MODULE(), MAKEINTRESOURCE(IDD_DISCONNECT),
                        nullptr, DialogProc, reinterpret_cast<LPARAM>(this));
  if (!hwnd_)
    return false;

  // Set up handler for Ctrl-Alt-Esc shortcut.
  if (!has_hotkey_ && RegisterHotKey(hwnd_, DISCONNECT_HOTKEY_ID,
                                     MOD_ALT | MOD_CONTROL, VK_ESCAPE)) {
    has_hotkey_ = true;
  }

  if (!SetStrings())
    return false;

  SetDialogPosition();
  ShowWindow(hwnd_, SW_SHOW);
  return IsWindowVisible(hwnd_) != FALSE;
}

void DisconnectWindowWin::EndDialog() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (has_hotkey_) {
    UnregisterHotKey(hwnd_, DISCONNECT_HOTKEY_ID);
    has_hotkey_ = false;
  }

  if (hwnd_) {
    DestroyWindow(hwnd_);
    hwnd_ = nullptr;
  }

  if (client_session_control_)
    client_session_control_->DisconnectSession(protocol::OK);
}

void DisconnectWindowWin::ShowDialog() {
  // Always reset the hide timer when this method is called.
  if (local_input_monitor_) {
    auto_hide_timer_.Start(FROM_HERE, kAutoHideTimeout,
                           base::BindOnce(&DisconnectWindowWin::HideDialog,
                                          base::Unretained(this)));
  }

  if (!was_auto_hidden_)
    return;

  // Make sure the dialog is fully visible when it is reshown.
  if (!local_input_seen_)
    SetDialogPosition();

  if (!AnimateWindow(hwnd_, kAnimationDurationMs, AW_BLEND)) {
    PLOG(ERROR) << "AnimateWindow() failed to show dialog: ";
    ShowWindow(hwnd_, SW_SHOW);

    // If the windows still isn't visible, then disconnect the session.
    if (!IsWindowVisible(hwnd_))
      client_session_control_->DisconnectSession(protocol::OK);
  }
  was_auto_hidden_ = false;
}

void DisconnectWindowWin::HideDialog() {
  if (was_auto_hidden_ || !local_input_monitor_)
    return;

  if (!AnimateWindow(hwnd_, kAnimationDurationMs, AW_BLEND | AW_HIDE))
    PLOG(ERROR) << "AnimateWindow() failed to show dialog: ";
  else
    was_auto_hidden_ = true;
}

void DisconnectWindowWin::StopAutoHideBehavior() {
  auto_hide_timer_.Stop();
  local_input_monitor_.reset();

  ShowDialog();
}

void DisconnectWindowWin::OnLocalMouseEvent(
    const webrtc::DesktopVector& position,
    ui::EventType type) {
  // Don't show the dialog if the position changes by ~1px in any direction.
  // This will prevent the dialog from being reshown due to small movements
  // caused by hardware/software issues which cause cursor drift or small
  // vibrations in the environment around the remote host.
  if (std::abs(position.x() - mouse_position_.x()) > 1 ||
      std::abs(position.y() - mouse_position_.y()) > 1) {
    // Show the dialog before setting |local_input_seen_|.  That way the dialog
    // will be shown in the center position and subsequent reshows will honor
    // the new position (if any) the dialog is moved to.
    ShowDialog();
    local_input_seen_ = true;
  }

  mouse_position_ = position;
}

void DisconnectWindowWin::OnLocalKeyboardEvent() {
  // Show the dialog before setting |local_input_seen_|.  That way the dialog
  // will be shown in the center position and subsequent reshows will honor
  // the new position (if any) the dialog is moved to.
  ShowDialog();
  local_input_seen_ = true;
}

void DisconnectWindowWin::DrawBorder(HWND hwnd, HDC hdc) {
  RECT rect;
  GetClientRect(hwnd, &rect);
  base::win::ScopedSelectObject border(hdc, border_pen_.get());
  base::win::ScopedSelectObject brush(hdc, GetStockObject(NULL_BRUSH));
  RoundRect(hdc, rect.left, rect.top, rect.right - 1, rect.bottom - 1,
            kWindowBorderRadius, kWindowBorderRadius);
}

// Returns |control| rectangle in the dialog coordinates.
bool DisconnectWindowWin::GetControlRect(HWND control, RECT* rect) {
  if (!GetWindowRect(control, rect))
    return false;
  SetLastError(ERROR_SUCCESS);
  int result = MapWindowPoints(HWND_DESKTOP, hwnd_,
                               reinterpret_cast<LPPOINT>(rect), 2);
  if (!result && GetLastError() != ERROR_SUCCESS)
    return false;

  return true;
}

void DisconnectWindowWin::SetDialogPosition() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // Try to center the window above the task-bar. If that fails, use the
  // primary monitor. If that fails (very unlikely), use the default position.
  HWND taskbar = FindWindow(kShellTrayWindowName, nullptr);
  HMONITOR monitor = MonitorFromWindow(taskbar, MONITOR_DEFAULTTOPRIMARY);
  MONITORINFO monitor_info = {sizeof(monitor_info)};
  RECT window_rect;
  if (!GetMonitorInfo(monitor, &monitor_info) ||
      !GetWindowRect(hwnd_, &window_rect)) {
    return;
  }

  int window_width = window_rect.right - window_rect.left;
  int window_height = window_rect.bottom - window_rect.top;

  // Default settings will display the window above the taskbar and centered
  // along the x axis.
  int top = monitor_info.rcWork.bottom - window_height;
  int left =
      (monitor_info.rcWork.right + monitor_info.rcWork.left - window_width) / 2;

  // Adjust the top value if the window is in auto-hide mode and we have not
  // seen local input yet.  We adjust the position to make the dialog a bit more
  // obtrusive so that a local user will notice it before it auto-hides.
  if (local_input_monitor_ && !local_input_seen_)
    top = top * 0.7;

  SetWindowPos(hwnd_, nullptr, left, top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}

bool DisconnectWindowWin::SetStrings() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  // Localize the disconnect button text and measure length of the old and new
  // labels.
  HWND hwnd_button = GetDlgItem(hwnd_, IDC_DISCONNECT);
  HWND hwnd_message = GetDlgItem(hwnd_, IDC_DISCONNECT_SHARINGWITH);
  if (!hwnd_button || !hwnd_message)
    return false;

  base::string16 button_text;
  base::string16 message_text;
  if (!GetControlText(hwnd_button, &button_text) ||
      !GetControlText(hwnd_message, &message_text)) {
    return false;
  }

  // Format and truncate "Your desktop is shared with ..." message.
  message_text = base::ReplaceStringPlaceholders(message_text,
                                                 base::UTF8ToUTF16(username_),
                                                 nullptr);
  if (message_text.length() > kMaxSharingWithTextLength)
    message_text.erase(kMaxSharingWithTextLength);

  if (!SetWindowText(hwnd_message, message_text.c_str()))
    return false;

  // Calculate the margin between controls in pixels.
  RECT rect = {0};
  rect.right = kWindowTextMargin;
  if (!MapDialogRect(hwnd_, &rect))
    return false;
  int margin = rect.right;

  // Resize |hwnd_message| so that the text is not clipped.
  RECT message_rect;
  if (!GetControlRect(hwnd_message, &message_rect))
    return false;

  LONG control_width;
  if (!GetControlTextWidth(hwnd_message, message_text, &control_width))
    return false;
  message_rect.right = message_rect.left + control_width + margin;

  if (!SetWindowPos(hwnd_message, nullptr,
                    message_rect.left, message_rect.top,
                    message_rect.right - message_rect.left,
                    message_rect.bottom - message_rect.top,
                    SWP_NOZORDER)) {
    return false;
  }

  // Reposition and resize |hwnd_button| as well.
  RECT button_rect;
  if (!GetControlRect(hwnd_button, &button_rect))
    return false;

  if (!GetControlTextWidth(hwnd_button, button_text, &control_width))
    return false;

  button_rect.left = message_rect.right;
  button_rect.right = button_rect.left + control_width + margin * 2;
  if (!SetWindowPos(hwnd_button, nullptr,
                    button_rect.left, button_rect.top,
                    button_rect.right - button_rect.left,
                    button_rect.bottom - button_rect.top,
                    SWP_NOZORDER)) {
    return false;
  }

  // Resize the whole window to fit the resized controls.
  RECT window_rect;
  if (!GetWindowRect(hwnd_, &window_rect))
    return false;
  int width = button_rect.right + margin;
  int height = window_rect.bottom - window_rect.top;
  if (!SetWindowPos(hwnd_, nullptr, 0, 0, width, height,
                    SWP_NOMOVE | SWP_NOZORDER)) {
    return false;
  }

  // Make the corners of the disconnect window rounded.
  HRGN rgn = CreateRoundRectRgn(0, 0, width, height, kWindowBorderRadius,
                                kWindowBorderRadius);
  if (!rgn)
    return false;
  if (!SetWindowRgn(hwnd_, rgn, TRUE))
    return false;

  return true;
}

} // namespace

// static
std::unique_ptr<HostWindow> HostWindow::CreateDisconnectWindow() {
  return std::make_unique<DisconnectWindowWin>();
}

std::unique_ptr<HostWindow> HostWindow::CreateAutoHidingDisconnectWindow(
    std::unique_ptr<LocalInputMonitor> local_input_monitor) {
  auto disconnect_window = std::make_unique<DisconnectWindowWin>();
  disconnect_window->EnableAutoHide(std::move(local_input_monitor));

  return disconnect_window;
}

}  // namespace remoting
