// 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 "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"

#include <algorithm>
#include <utility>

#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/autofill/autofill_popup_view.h"
#include "components/autofill/core/browser/autofill_popup_delegate.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "grit/webkit_resources.h"
#include "third_party/WebKit/public/web/WebAutofillClient.h"
#include "ui/events/event.h"
#include "ui/gfx/display.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/text_elider.h"
#include "ui/gfx/vector2d.h"

using base::WeakPtr;
using WebKit::WebAutofillClient;

namespace autofill {
namespace {

// Used to indicate that no line is currently selected by the user.
const int kNoSelection = -1;

// The vertical height of each row in pixels.
const size_t kRowHeight = 24;

// The vertical height of a separator in pixels.
const size_t kSeparatorHeight = 1;

#if !defined(OS_ANDROID)
// Size difference between name and subtext in pixels.
const int kLabelFontSizeDelta = -2;

const size_t kNamePadding = AutofillPopupView::kNamePadding;
const size_t kIconPadding = AutofillPopupView::kIconPadding;
const size_t kEndPadding = AutofillPopupView::kEndPadding;
const size_t kAutofillIconWidth = AutofillPopupView::kAutofillIconWidth;
#endif

struct DataResource {
  const char* name;
  int id;
};

const DataResource kDataResources[] = {
  { "americanExpressCC", IDR_AUTOFILL_CC_AMEX },
  { "dinersCC", IDR_AUTOFILL_CC_DINERS },
  { "discoverCC", IDR_AUTOFILL_CC_DISCOVER },
  { "genericCC", IDR_AUTOFILL_CC_GENERIC },
  { "jcbCC", IDR_AUTOFILL_CC_JCB },
  { "masterCardCC", IDR_AUTOFILL_CC_MASTERCARD },
  { "visaCC", IDR_AUTOFILL_CC_VISA },
};

}  // namespace

// static
WeakPtr<AutofillPopupControllerImpl> AutofillPopupControllerImpl::GetOrCreate(
    WeakPtr<AutofillPopupControllerImpl> previous,
    WeakPtr<AutofillPopupDelegate> delegate,
    gfx::NativeView container_view,
    const gfx::RectF& element_bounds,
    base::i18n::TextDirection text_direction) {
  DCHECK(!previous.get() || previous->delegate_.get() == delegate.get());

  if (previous.get() && previous->container_view() == container_view &&
      previous->element_bounds() == element_bounds) {
    previous->ClearState();
    return previous;
  }

  if (previous.get())
    previous->Hide();

  AutofillPopupControllerImpl* controller =
      new AutofillPopupControllerImpl(
          delegate, container_view, element_bounds, text_direction);
  return controller->GetWeakPtr();
}

AutofillPopupControllerImpl::AutofillPopupControllerImpl(
    base::WeakPtr<AutofillPopupDelegate> delegate,
    gfx::NativeView container_view,
    const gfx::RectF& element_bounds,
    base::i18n::TextDirection text_direction)
    : view_(NULL),
      delegate_(delegate),
      container_view_(container_view),
      element_bounds_(element_bounds),
      text_direction_(text_direction),
      hide_on_outside_click_(false),
      key_press_event_callback_(
          base::Bind(&AutofillPopupControllerImpl::HandleKeyPressEvent,
                     base::Unretained(this))),
      weak_ptr_factory_(this) {
  ClearState();
#if !defined(OS_ANDROID)
  subtext_font_ = name_font_.DeriveFont(kLabelFontSizeDelta);
  warning_font_ = name_font_.DeriveFont(0, gfx::Font::ITALIC);
#endif
}

AutofillPopupControllerImpl::~AutofillPopupControllerImpl() {}

void AutofillPopupControllerImpl::Show(
    const std::vector<string16>& names,
    const std::vector<string16>& subtexts,
    const std::vector<string16>& icons,
    const std::vector<int>& identifiers) {
  SetValues(names, subtexts, icons, identifiers);

#if !defined(OS_ANDROID)
  // Android displays the long text with ellipsis using the view attributes.

  UpdatePopupBounds();
  int popup_width = popup_bounds().width();

  // Elide the name and subtext strings so that the popup fits in the available
  // space.
  for (size_t i = 0; i < names_.size(); ++i) {
    int name_width = GetNameFontForRow(i).GetStringWidth(names_[i]);
    int subtext_width = subtext_font().GetStringWidth(subtexts_[i]);
    int total_text_length = name_width + subtext_width;

    // The line can have no strings if it represents a UI element, such as
    // a separator line.
    if (total_text_length == 0)
      continue;

    int available_width = popup_width - RowWidthWithoutText(i);

    // Each field recieves space in proportion to its length.
    int name_size = available_width * name_width / total_text_length;
    names_[i] = gfx::ElideText(names_[i],
                              GetNameFontForRow(i),
                              name_size,
                              gfx::ELIDE_AT_END);

    int subtext_size = available_width * subtext_width / total_text_length;
    subtexts_[i] = gfx::ElideText(subtexts_[i],
                                 subtext_font(),
                                 subtext_size,
                                 gfx::ELIDE_AT_END);
  }
#endif

  if (!view_) {
    view_ = AutofillPopupView::Create(this);

    // It is possible to fail to create the popup, in this case
    // treat the popup as hiding right away.
    if (!view_) {
      Hide();
      return;
    }

    ShowView();
  } else {
    UpdateBoundsAndRedrawPopup();
  }

  delegate_->OnPopupShown(&key_press_event_callback_);
}

void AutofillPopupControllerImpl::UpdateDataListValues(
    const std::vector<base::string16>& values,
    const std::vector<base::string16>& labels) {
  // Remove all the old data list values, which should always be at the top of
  // the list if they are present.
  while (!identifiers_.empty() &&
         identifiers_[0] == WebAutofillClient::MenuItemIDDataListEntry) {
    names_.erase(names_.begin());
    subtexts_.erase(subtexts_.begin());
    icons_.erase(icons_.begin());
    identifiers_.erase(identifiers_.begin());
  }

  // If there are no new data list values, exit (clearing the separator if there
  // is one).
  if (values.empty()) {
    if (!identifiers_.empty() &&
        identifiers_[0] == WebAutofillClient::MenuItemIDSeparator) {
      names_.erase(names_.begin());
      subtexts_.erase(subtexts_.begin());
      icons_.erase(icons_.begin());
      identifiers_.erase(identifiers_.begin());
    }

     // The popup contents have changed, so either update the bounds or hide it.
    if (HasSuggestions())
      UpdateBoundsAndRedrawPopup();
    else
      Hide();

    return;
  }

  // Add a separator if there are any other values.
  if (!identifiers_.empty() &&
      identifiers_[0] != WebAutofillClient::MenuItemIDSeparator) {
    names_.insert(names_.begin(), string16());
    subtexts_.insert(subtexts_.begin(), string16());
    icons_.insert(icons_.begin(), string16());
    identifiers_.insert(identifiers_.begin(),
                        WebAutofillClient::MenuItemIDSeparator);
  }


  names_.insert(names_.begin(), values.begin(), values.end());
  subtexts_.insert(subtexts_.begin(), labels.begin(), labels.end());

  // Add the values that are the same for all data list elements.
  icons_.insert(icons_.begin(), values.size(), base::string16());
  identifiers_.insert(identifiers_.begin(),
                      values.size(),
                      WebAutofillClient::MenuItemIDDataListEntry);

  UpdateBoundsAndRedrawPopup();
}

void AutofillPopupControllerImpl::Hide() {
  if (delegate_.get())
    delegate_->OnPopupHidden(&key_press_event_callback_);

  if (view_)
    view_->Hide();

  delete this;
}

void AutofillPopupControllerImpl::ViewDestroyed() {
  // The view has already been destroyed so clear the reference to it.
  view_ = NULL;

  Hide();
}

bool AutofillPopupControllerImpl::HandleKeyPressEvent(
    const content::NativeWebKeyboardEvent& event) {
  switch (event.windowsKeyCode) {
    case ui::VKEY_UP:
      SelectPreviousLine();
      return true;
    case ui::VKEY_DOWN:
      SelectNextLine();
      return true;
    case ui::VKEY_PRIOR:  // Page up.
      SetSelectedLine(0);
      return true;
    case ui::VKEY_NEXT:  // Page down.
      SetSelectedLine(names().size() - 1);
      return true;
    case ui::VKEY_ESCAPE:
      Hide();
      return true;
    case ui::VKEY_DELETE:
      return (event.modifiers & content::NativeWebKeyboardEvent::ShiftKey) &&
             RemoveSelectedLine();
    case ui::VKEY_TAB:
      // A tab press should cause the highlighted line to be selected, but still
      // return false so the tab key press propagates and changes the cursor
      // location.
      AcceptSelectedLine();
      return false;
    case ui::VKEY_RETURN:
      return AcceptSelectedLine();
    default:
      return false;
  }
}

void AutofillPopupControllerImpl::UpdateBoundsAndRedrawPopup() {
#if !defined(OS_ANDROID)
  // TODO(csharp): Since UpdatePopupBounds can change the position of the popup,
  // the popup could end up jumping from above the element to below it.
  // It is unclear if it is better to keep the popup where it was, or if it
  // should try and move to its desired position.
  UpdatePopupBounds();
#endif

  view_->UpdateBoundsAndRedrawPopup();
}

void AutofillPopupControllerImpl::MouseHovered(int x, int y) {
  SetSelectedLine(LineFromY(y));
}

void AutofillPopupControllerImpl::MouseClicked(int x, int y) {
  MouseHovered(x, y);
  AcceptSelectedLine();
}

void AutofillPopupControllerImpl::MouseExitedPopup() {
  SetSelectedLine(kNoSelection);
}

bool AutofillPopupControllerImpl::ShouldRepostEvent(
    const ui::MouseEvent& event) {
  return delegate_->ShouldRepostEvent(event);
}

void AutofillPopupControllerImpl::AcceptSuggestion(size_t index) {
  delegate_->DidAcceptSuggestion(full_names_[index], identifiers_[index]);
}

int AutofillPopupControllerImpl::GetIconResourceID(
    const string16& resource_name) {
  for (size_t i = 0; i < arraysize(kDataResources); ++i) {
    if (resource_name == ASCIIToUTF16(kDataResources[i].name))
      return kDataResources[i].id;
  }

  return -1;
}

bool AutofillPopupControllerImpl::CanDelete(size_t index) const {
  // TODO(isherman): Native AddressBook suggestions on Mac and Android should
  // not be considered to be deleteable.
  int id = identifiers_[index];
  return id > 0 ||
      id == WebAutofillClient::MenuItemIDAutocompleteEntry ||
      id == WebAutofillClient::MenuItemIDPasswordEntry;
}

bool AutofillPopupControllerImpl::IsWarning(size_t index) const {
  return identifiers_[index] == WebAutofillClient::MenuItemIDWarningMessage;
}

gfx::Rect AutofillPopupControllerImpl::GetRowBounds(size_t index) {
  int top = 0;
  for (size_t i = 0; i < index; ++i) {
    top += GetRowHeightFromId(identifiers()[i]);
  }

  return gfx::Rect(
      0,
      top,
      popup_bounds_.width(),
      GetRowHeightFromId(identifiers()[index]));
}

void AutofillPopupControllerImpl::SetPopupBounds(const gfx::Rect& bounds) {
  popup_bounds_ = bounds;
  UpdateBoundsAndRedrawPopup();
}

const gfx::Rect& AutofillPopupControllerImpl::popup_bounds() const {
  return popup_bounds_;
}

gfx::NativeView AutofillPopupControllerImpl::container_view() const {
  return container_view_;
}

const gfx::RectF& AutofillPopupControllerImpl::element_bounds() const {
  return element_bounds_;
}

bool AutofillPopupControllerImpl::IsRTL() const {
  return text_direction_ == base::i18n::RIGHT_TO_LEFT;
}

bool AutofillPopupControllerImpl::hide_on_outside_click() const {
  return hide_on_outside_click_;
}

const std::vector<string16>& AutofillPopupControllerImpl::names() const {
  return names_;
}

const std::vector<string16>& AutofillPopupControllerImpl::subtexts() const {
  return subtexts_;
}

const std::vector<string16>& AutofillPopupControllerImpl::icons() const {
  return icons_;
}

const std::vector<int>& AutofillPopupControllerImpl::identifiers() const {
  return identifiers_;
}

#if !defined(OS_ANDROID)
const gfx::Font& AutofillPopupControllerImpl::GetNameFontForRow(size_t index)
    const {
  if (identifiers_[index] == WebAutofillClient::MenuItemIDWarningMessage)
    return warning_font_;

  return name_font_;
}

const gfx::Font& AutofillPopupControllerImpl::subtext_font() const {
  return subtext_font_;
}
#endif

int AutofillPopupControllerImpl::selected_line() const {
  return selected_line_;
}

void AutofillPopupControllerImpl::set_hide_on_outside_click(
    bool hide_on_outside_click) {
  hide_on_outside_click_ = hide_on_outside_click;
}

void AutofillPopupControllerImpl::SetSelectedLine(int selected_line) {
  if (selected_line_ == selected_line)
    return;

  if (selected_line_ != kNoSelection &&
      static_cast<size_t>(selected_line_) < identifiers_.size())
    InvalidateRow(selected_line_);

  if (selected_line != kNoSelection)
    InvalidateRow(selected_line);

  selected_line_ = selected_line;

  if (selected_line_ != kNoSelection)
    delegate_->DidSelectSuggestion(identifiers_[selected_line_]);
  else
    delegate_->ClearPreviewedForm();
}

void AutofillPopupControllerImpl::SelectNextLine() {
  int new_selected_line = selected_line_ + 1;

  // Skip over any lines that can't be selected.
  while (static_cast<size_t>(new_selected_line) < names_.size() &&
         !CanAccept(identifiers()[new_selected_line])) {
    ++new_selected_line;
  }

  if (new_selected_line >= static_cast<int>(names_.size()))
    new_selected_line = 0;

  SetSelectedLine(new_selected_line);
}

void AutofillPopupControllerImpl::SelectPreviousLine() {
  int new_selected_line = selected_line_ - 1;

  // Skip over any lines that can't be selected.
  while (new_selected_line > kNoSelection &&
         !CanAccept(identifiers()[new_selected_line])) {
    --new_selected_line;
  }

  if (new_selected_line <= kNoSelection)
    new_selected_line = names_.size() - 1;

  SetSelectedLine(new_selected_line);
}

bool AutofillPopupControllerImpl::AcceptSelectedLine() {
  if (selected_line_ == kNoSelection)
    return false;

  DCHECK_GE(selected_line_, 0);
  DCHECK_LT(selected_line_, static_cast<int>(names_.size()));

  if (!CanAccept(identifiers_[selected_line_]))
    return false;

  AcceptSuggestion(selected_line_);
  return true;
}

bool AutofillPopupControllerImpl::RemoveSelectedLine() {
  if (selected_line_ == kNoSelection)
    return false;

  DCHECK_GE(selected_line_, 0);
  DCHECK_LT(selected_line_, static_cast<int>(names_.size()));

  if (!CanDelete(selected_line_))
    return false;

  delegate_->RemoveSuggestion(full_names_[selected_line_],
                              identifiers_[selected_line_]);

  // Remove the deleted element.
  names_.erase(names_.begin() + selected_line_);
  full_names_.erase(full_names_.begin() + selected_line_);
  subtexts_.erase(subtexts_.begin() + selected_line_);
  icons_.erase(icons_.begin() + selected_line_);
  identifiers_.erase(identifiers_.begin() + selected_line_);

  SetSelectedLine(kNoSelection);

  if (HasSuggestions()) {
    delegate_->ClearPreviewedForm();
    UpdateBoundsAndRedrawPopup();
  } else {
    Hide();
  }

  return true;
}

int AutofillPopupControllerImpl::LineFromY(int y) {
  int current_height = 0;

  for (size_t i = 0; i < identifiers().size(); ++i) {
    current_height += GetRowHeightFromId(identifiers()[i]);

    if (y <= current_height)
      return i;
  }

  // The y value goes beyond the popup so stop the selection at the last line.
  return identifiers().size() - 1;
}

int AutofillPopupControllerImpl::GetRowHeightFromId(int identifier) const {
  if (identifier == WebAutofillClient::MenuItemIDSeparator)
    return kSeparatorHeight;

  return kRowHeight;
}

bool AutofillPopupControllerImpl::CanAccept(int id) {
  return id != WebAutofillClient::MenuItemIDSeparator &&
      id != WebAutofillClient::MenuItemIDWarningMessage;
}

bool AutofillPopupControllerImpl::HasSuggestions() {
  return identifiers_.size() != 0 &&
      (identifiers_[0] > 0 ||
       identifiers_[0] ==
           WebAutofillClient::MenuItemIDAutocompleteEntry ||
       identifiers_[0] == WebAutofillClient::MenuItemIDPasswordEntry ||
       identifiers_[0] == WebAutofillClient::MenuItemIDDataListEntry);
}

void AutofillPopupControllerImpl::SetValues(
    const std::vector<string16>& names,
    const std::vector<string16>& subtexts,
    const std::vector<string16>& icons,
    const std::vector<int>& identifiers) {
  names_ = names;
  full_names_ = names;
  subtexts_ = subtexts;
  icons_ = icons;
  identifiers_ = identifiers;
}

void AutofillPopupControllerImpl::ShowView() {
  view_->Show();
}

void AutofillPopupControllerImpl::InvalidateRow(size_t row) {
  DCHECK(0 <= row);
  DCHECK(row < identifiers_.size());
  view_->InvalidateRow(row);
}

#if !defined(OS_ANDROID)
int AutofillPopupControllerImpl::GetDesiredPopupWidth() const {
  if (!name_font_.platform_font() || !subtext_font_.platform_font()) {
    // We can't calculate the size of the popup if the fonts
    // aren't present.
    return 0;
  }

  int popup_width = RoundedElementBounds().width();
  DCHECK_EQ(names().size(), subtexts().size());
  for (size_t i = 0; i < names().size(); ++i) {
    int row_size = name_font_.GetStringWidth(names()[i]) +
        subtext_font_.GetStringWidth(subtexts()[i]) +
        RowWidthWithoutText(i);

    popup_width = std::max(popup_width, row_size);
  }

  return popup_width;
}

int AutofillPopupControllerImpl::GetDesiredPopupHeight() const {
  int popup_height = 0;

  for (size_t i = 0; i < identifiers().size(); ++i) {
    popup_height += GetRowHeightFromId(identifiers()[i]);
  }

  return popup_height;
}

int AutofillPopupControllerImpl::RowWidthWithoutText(int row) const {
  int row_size = kEndPadding;

  if (!subtexts_[row].empty())
    row_size += kNamePadding;

  // Add the Autofill icon size, if required.
  if (!icons_[row].empty())
    row_size += kAutofillIconWidth + kIconPadding;

  // Add the padding at the end
  row_size += kEndPadding;

  return row_size;
}

void AutofillPopupControllerImpl::UpdatePopupBounds() {
  int popup_required_width = GetDesiredPopupWidth();
  int popup_height = GetDesiredPopupHeight();
  // This is the top left point of the popup if the popup is above the element
  // and grows to the left (since that is the highest and furthest left the
  // popup go could).
  gfx::Point top_left_corner_of_popup = RoundedElementBounds().origin() +
      gfx::Vector2d(RoundedElementBounds().width() - popup_required_width,
                    -popup_height);

  // This is the bottom right point of the popup if the popup is below the
  // element and grows to the right (since the is the lowest and furthest right
  // the popup could go).
  gfx::Point bottom_right_corner_of_popup = RoundedElementBounds().origin() +
      gfx::Vector2d(popup_required_width,
                    RoundedElementBounds().height() + popup_height);

  gfx::Display top_left_display = GetDisplayNearestPoint(
      top_left_corner_of_popup);
  gfx::Display bottom_right_display = GetDisplayNearestPoint(
      bottom_right_corner_of_popup);

  std::pair<int, int> popup_x_and_width = CalculatePopupXAndWidth(
      top_left_display, bottom_right_display, popup_required_width);
  std::pair<int, int> popup_y_and_height = CalculatePopupYAndHeight(
      top_left_display, bottom_right_display, popup_height);

  popup_bounds_ = gfx::Rect(popup_x_and_width.first,
                            popup_y_and_height.first,
                            popup_x_and_width.second,
                            popup_y_and_height.second);
}
#endif  // !defined(OS_ANDROID)

WeakPtr<AutofillPopupControllerImpl> AutofillPopupControllerImpl::GetWeakPtr() {
  return weak_ptr_factory_.GetWeakPtr();
}

void AutofillPopupControllerImpl::ClearState() {
  // Don't clear view_, because otherwise the popup will have to get regenerated
  // and this will cause flickering.

  popup_bounds_ = gfx::Rect();

  names_.clear();
  subtexts_.clear();
  icons_.clear();
  identifiers_.clear();
  full_names_.clear();

  selected_line_ = kNoSelection;
}

const gfx::Rect AutofillPopupControllerImpl::RoundedElementBounds() const {
  return gfx::ToEnclosingRect(element_bounds_);
}

gfx::Display AutofillPopupControllerImpl::GetDisplayNearestPoint(
    const gfx::Point& point) const {
  return gfx::Screen::GetScreenFor(container_view())->GetDisplayNearestPoint(
      point);
}

std::pair<int, int> AutofillPopupControllerImpl::CalculatePopupXAndWidth(
    const gfx::Display& left_display,
    const gfx::Display& right_display,
    int popup_required_width) const {
  int leftmost_display_x = left_display.bounds().x();
  int rightmost_display_x =
      right_display.GetSizeInPixel().width() + right_display.bounds().x();

  // Calculate the start coordinates for the popup if it is growing right or
  // the end position if it is growing to the left, capped to screen space.
  int right_growth_start = std::max(leftmost_display_x,
                                    std::min(rightmost_display_x,
                                             RoundedElementBounds().x()));
  int left_growth_end = std::max(leftmost_display_x,
                                   std::min(rightmost_display_x,
                                            RoundedElementBounds().right()));

  int right_available = rightmost_display_x - right_growth_start;
  int left_available = left_growth_end - leftmost_display_x;

  int popup_width = std::min(popup_required_width,
                             std::max(right_available, left_available));

  // If there is enough space for the popup on the right, show it there,
  // otherwise choose the larger size.
  if (right_available >= popup_width || right_available >= left_available)
    return std::make_pair(right_growth_start, popup_width);
  else
    return std::make_pair(left_growth_end - popup_width, popup_width);
}

std::pair<int,int> AutofillPopupControllerImpl::CalculatePopupYAndHeight(
    const gfx::Display& top_display,
    const gfx::Display& bottom_display,
    int popup_required_height) const {
  int topmost_display_y = top_display.bounds().y();
  int bottommost_display_y =
      bottom_display.GetSizeInPixel().height() + bottom_display.bounds().y();

  // Calculate the start coordinates for the popup if it is growing down or
  // the end position if it is growing up, capped to screen space.
  int top_growth_end = std::max(topmost_display_y,
                                std::min(bottommost_display_y,
                                         RoundedElementBounds().y()));
  int bottom_growth_start = std::max(topmost_display_y,
      std::min(bottommost_display_y, RoundedElementBounds().bottom()));

  int top_available = bottom_growth_start - topmost_display_y;
  int bottom_available = bottommost_display_y - top_growth_end;

  // TODO(csharp): Restrict the popup height to what is available.
  if (bottom_available >= popup_required_height ||
      bottom_available >= top_available) {
    // The popup can appear below the field.
    return std::make_pair(bottom_growth_start, popup_required_height);
  } else {
    // The popup must appear above the field.
    return std::make_pair(top_growth_end - popup_required_height,
                          popup_required_height);
  }
}

}  // namespace autofill
