// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/system/virtual_keyboard/virtual_keyboard_tray.h"

#include <algorithm>

#include "ash/accessibility/accessibility_controller.h"
#include "ash/constants/tray_background_view_catalog.h"
#include "ash/keyboard/ui/keyboard_ui_controller.h"
#include "ash/metrics/user_metrics_recorder.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shelf/shelf.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_id.h"
#include "ash/system/tray/tray_constants.h"
#include "ash/system/tray/tray_container.h"
#include "chromeos/constants/chromeos_features.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/models/image_model.h"
#include "ui/views/border.h"
#include "ui/views/controls/image_view.h"

namespace ui {
class Event;
}  // namespace ui

namespace ash {

class TrayBubbleView;

VirtualKeyboardTray::VirtualKeyboardTray(
    Shelf* shelf,
    TrayBackgroundViewCatalogName catalog_name)
    : ImagedTrayIcon(shelf,
                     ui::ImageModel::FromVectorIcon(kShelfKeyboardNewuiIcon,
                                                    kColorAshIconColorPrimary),
                     /*tooltip=*/
                     IDS_ASH_STATUS_TRAY_ACCESSIBILITY_VIRTUAL_KEYBOARD,
                     /*accessibility_name=*/
                     IDS_ASH_VIRTUAL_KEYBOARD_TRAY_ACCESSIBLE_NAME,
                     catalog_name) {
  SetCallback(base::BindRepeating(&VirtualKeyboardTray::OnButtonPressed,
                                  base::Unretained(this)));

  // First sets the image with non-Jelly color to get the image dimension and
  // create the correct paddings, and then updates the color if Jelly is
  // enabled.
  UpdateTrayItemColor(is_active());

  // The Shell may not exist in some unit tests.
  if (Shell::HasInstance()) {
    Shell::Get()->accessibility_controller()->AddObserver(this);
    Shell::Get()->AddShellObserver(this);
    keyboard::KeyboardUIController::Get()->AddObserver(this);
  }
}

VirtualKeyboardTray::~VirtualKeyboardTray() {
  // The Shell may not exist in some unit tests.
  if (!Shell::HasInstance()) {
    return;
  }

  keyboard::KeyboardUIController::Get()->RemoveObserver(this);
  Shell::Get()->RemoveShellObserver(this);
  Shell::Get()->accessibility_controller()->RemoveObserver(this);
}

void VirtualKeyboardTray::OnButtonPressed(const ui::Event& event) {
  UserMetricsRecorder::RecordUserClickOnTray(
      LoginMetricsRecorder::TrayClickTarget::kVirtualKeyboardTray);

  auto* keyboard_controller = keyboard::KeyboardUIController::Get();

  // Keyboard may not always be enabled. https://crbug.com/749989
  if (!keyboard_controller->IsEnabled()) {
    return;
  }

  // Normally, active status is set when virtual keyboard is shown/hidden,
  // however, showing virtual keyboard happens asynchronously and, especially
  // the first time, takes some time. We need to set active status here to
  // prevent bad things happening if user clicked the button before keyboard is
  // shown.
  if (is_active()) {
    keyboard_controller->HideKeyboardByUser();
    SetIsActive(false);
    return;
  }
  keyboard_controller->ShowKeyboardInDisplay(
      display::Screen::Get()->GetDisplayNearestWindow(shelf()->GetWindow()));
  SetIsActive(true);
}

void VirtualKeyboardTray::Initialize() {
  TrayBackgroundView::Initialize();
  SetVisiblePreferred(
      Shell::Get()->accessibility_controller()->virtual_keyboard().enabled());
}

void VirtualKeyboardTray::HideBubbleWithView(
    const TrayBubbleView* bubble_view) {}

void VirtualKeyboardTray::ClickedOutsideBubble(const ui::LocatedEvent& event) {}

void VirtualKeyboardTray::UpdateTrayItemColor(bool is_active) {
  image_view()->SetImage(ui::ImageModel::FromVectorIcon(
      kShelfKeyboardNewuiIcon,
      is_active ? cros_tokens::kCrosSysSystemOnPrimaryContainer
                : cros_tokens::kCrosSysOnSurface));
}

void VirtualKeyboardTray::HideBubble(const TrayBubbleView* bubble_view) {}

void VirtualKeyboardTray::OnAccessibilityStatusChanged() {
  bool new_enabled =
      Shell::Get()->accessibility_controller()->virtual_keyboard().enabled();
  SetVisiblePreferred(new_enabled);
}

void VirtualKeyboardTray::OnKeyboardVisibilityChanged(const bool is_visible) {
  SetIsActive(is_visible);
}

BEGIN_METADATA(VirtualKeyboardTray);
END_METADATA

}  // namespace ash
