// Copyright 2016 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 "ash/system/ime_menu/ime_list_view.h"

#include "ash/ime/ime_controller.h"
#include "ash/ime/ime_switch_type.h"
#include "ash/keyboard/ash_keyboard_controller.h"
#include "ash/keyboard/ui/keyboard_util.h"
#include "ash/keyboard/virtual_keyboard_controller.h"
#include "ash/public/interfaces/ime_info.mojom.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/tray/actionable_view.h"
#include "ash/system/tray/system_menu_button.h"
#include "ash/system/tray/tray_constants.h"
#include "ash/system/tray/tray_detailed_view.h"
#include "ash/system/tray/tray_popup_item_style.h"
#include "ash/system/tray/tray_popup_utils.h"
#include "ash/system/tray/tri_view.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/toggle_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/separator.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/painter.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"

namespace ash {
namespace {

const int kMinFontSizeDelta = -10;

// Represents a row in the scrollable IME list; each row is either an IME or
// an IME property. A checkmark icon is shown in the row if selected.
class ImeListItemView : public ActionableView {
 public:
  ImeListItemView(ImeListView* list_view,
                  const base::string16& id,
                  const base::string16& label,
                  bool selected,
                  const SkColor button_color,
                  bool use_unified_theme)
      : ActionableView(TrayPopupInkDropStyle::FILL_BOUNDS),
        ime_list_view_(list_view),
        selected_(selected) {
    SetInkDropMode(InkDropMode::ON);

    TriView* tri_view = TrayPopupUtils::CreateDefaultRowView();
    AddChildView(tri_view);
    SetLayoutManager(std::make_unique<views::FillLayout>());

    // |id_label| contains the IME short name (e.g., 'US', 'GB', 'IT').
    views::Label* id_label = TrayPopupUtils::CreateDefaultLabel();
    if (use_unified_theme) {
      id_label->SetEnabledColor(kUnifiedMenuTextColor);
      id_label->SetAutoColorReadabilityEnabled(false);
    }
    id_label->SetText(id);
    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    const gfx::FontList& base_font_list =
        rb.GetFontList(ui::ResourceBundle::MediumBoldFont);
    id_label->SetFontList(base_font_list);

    // IMEs having a short name of more than two characters (e.g., 'INTL') will
    // elide if rendered within |kMenuIconSize|. Shrink the font size until the
    // entire short name fits within the bounds.
    int size_delta = -1;
    while ((id_label->GetPreferredSize().width() -
            id_label->GetInsets().width()) > kMenuIconSize &&
           size_delta >= kMinFontSizeDelta) {
      id_label->SetFontList(base_font_list.DeriveWithSizeDelta(size_delta));
      --size_delta;
    }
    tri_view->AddView(TriView::Container::START, id_label);

    // The label shows the IME full name.
    auto* label_view = TrayPopupUtils::CreateDefaultLabel();
    label_view->SetText(label);
    TrayPopupItemStyle style(TrayPopupItemStyle::FontStyle::DETAILED_VIEW_LABEL,
                             use_unified_theme);
    style.SetupLabel(label_view);

    label_view->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    tri_view->AddView(TriView::Container::CENTER, label_view);

    if (selected) {
      // The checked button indicates the IME is selected.
      views::ImageView* checked_image = TrayPopupUtils::CreateMainImageView();
      checked_image->SetImage(
          gfx::CreateVectorIcon(kCheckCircleIcon, kMenuIconSize, button_color));
      tri_view->AddView(TriView::Container::END, checked_image);
    }
    SetAccessibleName(label_view->GetText());
  }

  ~ImeListItemView() override = default;

  // ActionableView:
  bool PerformAction(const ui::Event& event) override {
    ime_list_view_->set_last_item_selected_with_keyboard(
        ime_list_view_->should_focus_ime_after_selection_with_keyboard() &&
        event.type() == ui::EventType::ET_KEY_PRESSED);
    ime_list_view_->HandleViewClicked(this);
    return true;
  }

  void OnFocus() override {
    ActionableView::OnFocus();
    if (ime_list_view_)
      ime_list_view_->ScrollItemToVisible(this);
  }

  void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
    ActionableView::GetAccessibleNodeData(node_data);
    node_data->role = ax::mojom::Role::kCheckBox;
    node_data->SetCheckedState(selected_ ? ax::mojom::CheckedState::kTrue
                                         : ax::mojom::CheckedState::kFalse);
  }

 private:
  ImeListView* ime_list_view_;
  bool selected_;

  DISALLOW_COPY_AND_ASSIGN(ImeListItemView);
};

}  // namespace

// Contains a toggle button to let the user enable/disable whether the
// on-screen keyboard should be shown when focusing a textfield. This row is
// shown only under certain conditions, e.g., when an external keyboard is
// attached and the user is in TabletMode mode.
class KeyboardStatusRow : public views::View {
 public:
  KeyboardStatusRow() = default;
  ~KeyboardStatusRow() override = default;

  views::ToggleButton* toggle() const { return toggle_; }

  void Init(views::ButtonListener* listener, bool use_unified_theme) {
    TrayPopupUtils::ConfigureAsStickyHeader(this);
    SetLayoutManager(std::make_unique<views::FillLayout>());

    TriView* tri_view = TrayPopupUtils::CreateDefaultRowView();
    AddChildView(tri_view);

    // The on-screen keyboard image button.
    views::ImageView* keyboard_image = TrayPopupUtils::CreateMainImageView();
    keyboard_image->SetImage(gfx::CreateVectorIcon(
        kImeMenuOnScreenKeyboardIcon, kMenuIconSize, kMenuIconColor));
    tri_view->AddView(TriView::Container::START, keyboard_image);

    // The on-screen keyboard label ('On-screen keyboard').
    auto* label = TrayPopupUtils::CreateDefaultLabel();
    label->SetText(ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
        IDS_ASH_STATUS_TRAY_ACCESSIBILITY_VIRTUAL_KEYBOARD));
    TrayPopupItemStyle style(TrayPopupItemStyle::FontStyle::DETAILED_VIEW_LABEL,
                             use_unified_theme);
    style.SetupLabel(label);
    tri_view->AddView(TriView::Container::CENTER, label);

    // The on-screen keyboard toggle button.
    toggle_ = TrayPopupUtils::CreateToggleButton(
        listener, IDS_ASH_STATUS_TRAY_ACCESSIBILITY_VIRTUAL_KEYBOARD);
    toggle_->SetIsOn(keyboard::IsKeyboardEnabled());
    tri_view->AddView(TriView::Container::END, toggle_);
  }

  // views::View:
  const char* GetClassName() const override { return "KeyboardStatusRow"; }

 private:
  // ToggleButton to toggle keyboard on or off.
  views::ToggleButton* toggle_ = nullptr;

  DISALLOW_COPY_AND_ASSIGN(KeyboardStatusRow);
};

ImeListView::ImeListView(DetailedViewDelegate* delegate)
    : ImeListView(delegate, true) {}

ImeListView::ImeListView(DetailedViewDelegate* delegate, bool use_unified_theme)
    : TrayDetailedView(delegate),
      last_item_selected_with_keyboard_(false),
      should_focus_ime_after_selection_with_keyboard_(false),
      current_ime_view_(nullptr),
      use_unified_theme_(use_unified_theme) {}

ImeListView::~ImeListView() = default;

void ImeListView::Init(bool show_keyboard_toggle,
                       SingleImeBehavior single_ime_behavior) {
  ImeController* ime_controller = Shell::Get()->ime_controller();
  Update(ime_controller->current_ime().id, ime_controller->available_imes(),
         ime_controller->current_ime_menu_items(), show_keyboard_toggle,
         single_ime_behavior);
}

void ImeListView::Update(const std::string& current_ime_id,
                         const std::vector<mojom::ImeInfo>& list,
                         const std::vector<mojom::ImeMenuItem>& property_items,
                         bool show_keyboard_toggle,
                         SingleImeBehavior single_ime_behavior) {
  ResetImeListView();
  ime_map_.clear();
  property_map_.clear();
  CreateScrollableList();

  if (single_ime_behavior == ImeListView::SHOW_SINGLE_IME || list.size() > 1)
    AppendImeListAndProperties(current_ime_id, list, property_items);

  if (show_keyboard_toggle)
    PrependKeyboardStatusRow();

  Layout();
  SchedulePaint();

  if (should_focus_ime_after_selection_with_keyboard_ &&
      last_item_selected_with_keyboard_) {
    FocusCurrentImeIfNeeded();
  } else if (current_ime_view_) {
    ScrollItemToVisible(current_ime_view_);
  }
}

void ImeListView::ResetImeListView() {
  // Children are removed from the view hierarchy and deleted in Reset().
  Reset();
  keyboard_status_row_ = nullptr;
  current_ime_view_ = nullptr;
}

void ImeListView::ScrollItemToVisible(views::View* item_view) {
  if (scroll_content())
    scroll_content()->ScrollRectToVisible(item_view->bounds());
}

void ImeListView::CloseImeListView() {
  last_selected_item_id_.clear();
  current_ime_view_ = nullptr;
  last_item_selected_with_keyboard_ = false;
  GetWidget()->Close();
}

void ImeListView::AppendImeListAndProperties(
    const std::string& current_ime_id,
    const std::vector<mojom::ImeInfo>& list,
    const std::vector<mojom::ImeMenuItem>& property_list) {
  DCHECK(ime_map_.empty());
  for (size_t i = 0; i < list.size(); i++) {
    const bool selected = current_ime_id == list[i].id;
    views::View* ime_view =
        new ImeListItemView(this, list[i].short_name, list[i].name, selected,
                            gfx::kGoogleGreen700, use_unified_theme_);
    scroll_content()->AddChildView(ime_view);
    ime_map_[ime_view] = list[i].id;

    if (selected)
      current_ime_view_ = ime_view;

    // Add the properties, if any, of the currently-selected IME.
    if (selected && !property_list.empty()) {
      // Adds a separator on the top of property items.
      scroll_content()->AddChildView(
          TrayPopupUtils::CreateListItemSeparator(true));

      // Adds the property items.
      for (size_t i = 0; i < property_list.size(); i++) {
        ImeListItemView* property_view = new ImeListItemView(
            this, base::string16(), property_list[i].label,
            property_list[i].checked, kMenuIconColor, use_unified_theme_);
        scroll_content()->AddChildView(property_view);
        property_map_[property_view] = property_list[i].key;
      }

      // Adds a separator on the bottom of property items if there are still
      // other IMEs under the current one.
      if (i < list.size() - 1)
        scroll_content()->AddChildView(
            TrayPopupUtils::CreateListItemSeparator(true));
    }
  }
}

void ImeListView::PrependKeyboardStatusRow() {
  DCHECK(!keyboard_status_row_);
  keyboard_status_row_ = new KeyboardStatusRow;
  keyboard_status_row_->Init(this, use_unified_theme_);
  scroll_content()->AddChildViewAt(keyboard_status_row_, 0);
}

void ImeListView::HandleViewClicked(views::View* view) {
  ImeController* ime_controller = Shell::Get()->ime_controller();
  std::map<views::View*, std::string>::const_iterator ime = ime_map_.find(view);
  if (ime != ime_map_.end()) {
    base::RecordAction(base::UserMetricsAction("StatusArea_IME_SwitchMode"));
    std::string ime_id = ime->second;
    last_selected_item_id_ = ime_id;
    ime_controller->SwitchImeById(ime_id, false /* show_message */);
    UMA_HISTOGRAM_ENUMERATION("InputMethod.ImeSwitch", ImeSwitchType::kTray);

  } else {
    std::map<views::View*, std::string>::const_iterator property =
        property_map_.find(view);
    if (property == property_map_.end())
      return;
    const std::string key = property->second;
    last_selected_item_id_ = key;
    ime_controller->ActivateImeMenuItem(key);
  }

  if (!should_focus_ime_after_selection_with_keyboard_ ||
      !last_item_selected_with_keyboard_) {
    CloseImeListView();
  }
}

void ImeListView::HandleButtonPressed(views::Button* sender,
                                      const ui::Event& event) {
  DCHECK_EQ(sender, keyboard_status_row_->toggle());

  Shell::Get()
      ->ash_keyboard_controller()
      ->virtual_keyboard_controller()
      ->ToggleIgnoreExternalKeyboard();
  last_selected_item_id_.clear();
  last_item_selected_with_keyboard_ = false;
}

void ImeListView::VisibilityChanged(View* starting_from, bool is_visible) {
  if (!is_visible || (should_focus_ime_after_selection_with_keyboard_ &&
                      last_item_selected_with_keyboard_) ||
      !current_ime_view_) {
    return;
  }

  ScrollItemToVisible(current_ime_view_);
}

const char* ImeListView::GetClassName() const {
  return "ImeListView";
}

void ImeListView::FocusCurrentImeIfNeeded() {
  views::FocusManager* manager = GetFocusManager();
  if (!manager || manager->GetFocusedView() || last_selected_item_id_.empty())
    return;

  for (auto ime_map : ime_map_) {
    if (ime_map.second == last_selected_item_id_) {
      (ime_map.first)->RequestFocus();
      return;
    }
  }

  for (auto property_map : property_map_) {
    if (property_map.second == last_selected_item_id_) {
      (property_map.first)->RequestFocus();
      return;
    }
  }
}

ImeListViewTestApi::ImeListViewTestApi(ImeListView* ime_list_view)
    : ime_list_view_(ime_list_view) {}

ImeListViewTestApi::~ImeListViewTestApi() = default;

views::View* ImeListViewTestApi::GetToggleView() const {
  return ime_list_view_->keyboard_status_row_->toggle();
}

}  // namespace ash
