// Copyright 2013 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 "ui/views/corewm/tooltip_win.h"

#include <winuser.h>

#include "base/debug/stack_trace.h"
#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "ui/base/l10n/l10n_util_win.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/win/dpi.h"
#include "ui/views/corewm/cursor_height_provider_win.h"

namespace views {
namespace corewm {

TooltipWin::TooltipWin(HWND parent)
    : parent_hwnd_(parent),
      tooltip_hwnd_(NULL),
      showing_(false) {
  memset(&toolinfo_, 0, sizeof(toolinfo_));
  toolinfo_.cbSize = sizeof(toolinfo_);
  toolinfo_.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
  toolinfo_.uId = reinterpret_cast<UINT_PTR>(parent_hwnd_);
  toolinfo_.hwnd = parent_hwnd_;
  toolinfo_.lpszText = NULL;
  toolinfo_.lpReserved = NULL;
  SetRectEmpty(&toolinfo_.rect);
}

TooltipWin::~TooltipWin() {
  if (tooltip_hwnd_)
    DestroyWindow(tooltip_hwnd_);
}

bool TooltipWin::HandleNotify(int w_param, NMHDR* l_param, LRESULT* l_result) {
  if (tooltip_hwnd_ == NULL)
    return false;

  switch (l_param->code) {
    case TTN_POP:
      showing_ = false;
      return true;
    case TTN_SHOW:
      *l_result = TRUE;
      PositionTooltip();
      showing_ = true;
      return true;
    default:
      break;
  }
  return false;
}

bool TooltipWin::EnsureTooltipWindow() {
  if (tooltip_hwnd_)
    return true;

  tooltip_hwnd_ = CreateWindowEx(
      WS_EX_TRANSPARENT | l10n_util::GetExtendedTooltipStyles(),
      TOOLTIPS_CLASS, NULL, TTS_NOPREFIX | WS_POPUP, 0, 0, 0, 0,
      parent_hwnd_, NULL, NULL, NULL);
  if (!tooltip_hwnd_) {
    PLOG(WARNING) << "tooltip creation failed, disabling tooltips";
    return false;
  }

  l10n_util::AdjustUIFontForWindow(tooltip_hwnd_);

  SendMessage(tooltip_hwnd_, TTM_ADDTOOL, 0,
              reinterpret_cast<LPARAM>(&toolinfo_));
  return true;
}

void TooltipWin::PositionTooltip() {
  // This code only runs for non-metro, so GetNativeScreen() is fine.
  gfx::Point screen_point = gfx::win::DIPToScreenPoint(location_);
  const int cursoroffset = GetCurrentCursorVisibleHeight();
  screen_point.Offset(0, cursoroffset);

  DWORD tooltip_size = SendMessage(tooltip_hwnd_, TTM_GETBUBBLESIZE, 0,
                                   reinterpret_cast<LPARAM>(&toolinfo_));
  const gfx::Size size(LOWORD(tooltip_size), HIWORD(tooltip_size));

  const gfx::Display display(
      gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(screen_point));

  gfx::Rect tooltip_bounds(screen_point, size);
  tooltip_bounds.AdjustToFit(gfx::win::DIPToScreenRect(display.work_area()));
  SetWindowPos(tooltip_hwnd_, NULL, tooltip_bounds.x(), tooltip_bounds.y(), 0,
               0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}

void TooltipWin::SetText(aura::Window* window,
                         const base::string16& tooltip_text,
                         const gfx::Point& location) {
  if (!EnsureTooltipWindow())
    return;

  // See comment in header for details on why |location_| is needed.
  location_ = location;

  // Without this we get a flicker of the tooltip appearing at 0x0. Not sure
  // why.
  SetWindowPos(tooltip_hwnd_, NULL, 0, 0, 0, 0,
               SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE |
               SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);

  base::string16 adjusted_text(tooltip_text);
  base::i18n::AdjustStringForLocaleDirection(&adjusted_text);
  toolinfo_.lpszText = const_cast<WCHAR*>(adjusted_text.c_str());
  SendMessage(tooltip_hwnd_, TTM_SETTOOLINFO, 0,
              reinterpret_cast<LPARAM>(&toolinfo_));

  // This code only runs for non-metro, so GetNativeScreen() is fine.
  const gfx::Point screen_point = gfx::win::DIPToScreenPoint(location_);
  gfx::Display display(
      gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(screen_point));
  const gfx::Rect monitor_bounds = display.bounds();
  int max_width = (monitor_bounds.width() + 1) / 2;
  SendMessage(tooltip_hwnd_, TTM_SETMAXTIPWIDTH, 0, max_width);
}

void TooltipWin::Show() {
  if (!EnsureTooltipWindow())
    return;

  SendMessage(tooltip_hwnd_, TTM_TRACKACTIVATE,
              TRUE, reinterpret_cast<LPARAM>(&toolinfo_));
  SetWindowPos(tooltip_hwnd_, HWND_TOPMOST, 0, 0, 0, 0,
               SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSIZE);
}

void TooltipWin::Hide() {
  if (!tooltip_hwnd_)
    return;

  SendMessage(tooltip_hwnd_, TTM_TRACKACTIVATE, FALSE,
              reinterpret_cast<LPARAM>(&toolinfo_));
}

bool TooltipWin::IsVisible() {
  return showing_;
}

}  // namespace corewm
}  // namespace views
