
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/toolbar/toolbar_glic_button.h"

#include "base/logging.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/glic/public/features.h"
#include "chrome/browser/ui/browser_element_identifiers.h"
#include "chrome/browser/ui/color/chrome_color_id.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/browser/ui/views/frame/browser_frame_view.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/glic/glic_button.h"
#include "chrome/browser/ui/views/interaction/browser_elements_views.h"
#include "chrome/browser/ui/views/toolbar/toolbar_button.h"
#include "chrome/browser/ui/views/toolbar/toolbar_glic_button.h"
#include "chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.h"
#include "components/vector_icons/vector_icons.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/ui_base_features.h"
#include "ui/color/color_id.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rounded_corners_f.h"
#include "ui/gfx/vector_icon_types.h"
#include "ui/views/animation/ink_drop.h"
#include "ui/views/background.h"

namespace {
constexpr int kCloseButtonSize = 16;
constexpr int kSpaceBetweenButtons = 2;
constexpr int kLabelToolbarButtonRightMargin = 6;
constexpr int kIconToolbarButtonLeftMargin = 3;
}  // namespace

namespace glic {

ToolbarGlicButton::ToolbarGlicButton(
    BrowserWindowInterface* browser_window_interface,
    base::RepeatingClosure expansion_animation_done_callback,
    const std::u16string& tooltip,
    PressedCallback pressed_callback)
    : GlicButton<ToolbarButton>(browser_window_interface,
                                expansion_animation_done_callback,
                                tooltip,
                                kToolbarGlicIconSize,
                                pressed_callback) {
  UpdateIcon();
  auto* image_view = static_cast<views::ImageView*>(image_container_view());
  image_view->SetImageSize({kToolbarGlicIconSize, kToolbarGlicIconSize});
  image_view->SetProperty(views::kMarginsKey,
                          gfx::Insets().set_left(kIconToolbarButtonLeftMargin));

  SetLabelMargins();

  UpdateColors();
}

ToolbarGlicButton::~ToolbarGlicButton() = default;

gfx::Size ToolbarGlicButton::CalculatePreferredSize(
    const views::SizeBounds& available_size) const {
  gfx::Size size =
      GlicButton<ToolbarButton>::CalculatePreferredSize(available_size);
  size.set_height(GetLayoutConstant(LayoutConstant::kToolbarButtonHeight));
  return size;
}

gfx::Size ToolbarGlicButton::GetMinimumSize() const {
  const int size = GetLayoutConstant(LayoutConstant::kToolbarButtonHeight);
  return gfx::Size(size, size);
}

void ToolbarGlicButton::AddedToWidget() {
  split_rounded_edge_radius_ = GetRoundedCornerRadius();
  SetLeftRightCornerRadii(GetRoundedCornerRadius(), GetRoundedCornerRadius());
  bool show_before_avatar =
      base::FeatureList::IsEnabled(features::kGlicToolbarButtonLocation) &&
      features::kGlicToolbarButtonLocationParam.Get() ==
          features::GlicToolbarButtonLocation::kLeftOfProfileChip;
  if (ShouldApplyCustomThemeFallback()) {
    SetDefaultBackgroundColorId(kColorAvatarButtonHighlightDefault);
  } else {
    SetDefaultBackgroundColorId(show_before_avatar
                                    ? kColorToolbar
                                    : kColorToolbarGlicButtonBackgroundDefault);
  }
  GlicButton<ToolbarButton>::AddedToWidget();
}

bool ToolbarGlicButton::IsWidgetAlive() const {
  const views::Widget* widget = GetWidget();
  return widget && !widget->IsClosed();
}

void ToolbarGlicButton::SetForegroundFrameActiveColorId(
    ui::ColorId new_color_id) {
  UpdateColors();
}
void ToolbarGlicButton::SetForegroundFrameInactiveColorId(
    ui::ColorId new_color_id) {
  UpdateColors();
}
void ToolbarGlicButton::SetBackgroundFrameActiveColorId(
    ui::ColorId new_color_id) {
  UpdateColors();
}
void ToolbarGlicButton::SetBackgroundFrameInactiveColorId(
    ui::ColorId new_color_id) {
  UpdateColors();
}

void ToolbarGlicButton::SetLeftRightCornerRadii(int left, int right) {
  left_corner_radius_ = left;
  right_corner_radius_ = right;
}

float ToolbarGlicButton::GetCornerRadiusFor(ToolbarButton::Edge edge) const {
  switch (edge) {
    case ToolbarButton::Edge::kLeft:
    case ToolbarButton::Edge::kTopLeft:
    case ToolbarButton::Edge::kBottomLeft:
      return left_corner_radius_.value_or(GetRoundedCornerRadius());
    case ToolbarButton::Edge::kRight:
    case ToolbarButton::Edge::kTopRight:
    case ToolbarButton::Edge::kBottomRight:
      return right_corner_radius_.value_or(GetRoundedCornerRadius());
  }
}

int ToolbarGlicButton::GetRoundedCornerRadius() const {
  return GetLayoutConstant(LayoutConstant::kToolbarButtonHeight) / 2;
}

int ToolbarGlicButton::GetSplitRoundedEdgeRadius() {
  return split_rounded_edge_radius_;
}

int ToolbarGlicButton::GetIconSize() const {
  return kToolbarGlicIconSize;
}

void ToolbarGlicButton::UpdateColors() {
  ToolbarButton::UpdateColorsAndInsets();
}

void ToolbarGlicButton::UpdateStyle(bool should_match_toolbar) {
  ChromeColorIds background_color_id =
      should_match_toolbar ? kColorToolbar
                           : kColorToolbarGlicButtonBackgroundDefault;

  if (ShouldApplyCustomThemeFallback()) {
    background_color_id = kColorAvatarButtonHighlightDefault;
  }

  SetDefaultBackgroundColorId(background_color_id);
  UpdateColors();
}

void ToolbarGlicButton::SetCloseButtonFocusBehavior(
    views::View::FocusBehavior focus_behavior) {}

void ToolbarGlicButton::SetLabelMargins() {
  const bool close_button_visible =
      close_button() && close_button()->GetVisible();
  this->label()->SetProperty(
      views::kMarginsKey,
      gfx::Insets().set_right(close_button_visible
                                  ? kLabelWithCloseButtonRightMargin
                                  : kLabelToolbarButtonRightMargin));
}

void ToolbarGlicButton::AddCloseButton(PressedCallback pressed_callback) {
  auto close_button =
      std::make_unique<views::LabelButton>(std::move(pressed_callback));
  close_button->SetTooltipText(
      l10n_util::GetStringUTF16(IDS_TOOLTIP_GLIC_CLOSE));

  const ui::ImageModel icon_image_model = ui::ImageModel::FromVectorIcon(
      features::IsRoundedIconsEnabled()
          ? vector_icons::kCloseIcon
          : vector_icons::kCloseChromeRefreshOldIcon,
      kColorTabSearchButtonCRForegroundFrameActive, kCloseButtonSize);

  close_button->SetImageModel(views::Button::STATE_NORMAL, icon_image_model);
  close_button->SetImageModel(views::Button::STATE_HOVERED, icon_image_model);
  close_button->SetImageModel(views::Button::STATE_PRESSED, icon_image_model);

  close_button->SetPaintToLayer();
  close_button->layer()->SetFillsBoundsOpaquely(false);

  views::InkDrop::Get(close_button.get())
      ->SetMode(views::InkDropHost::InkDropMode::ON);
  views::InkDrop::Get(close_button.get())->SetHighlightOpacity(0.16f);
  views::InkDrop::Get(close_button.get())->SetVisibleOpacity(0.14f);
  views::InkDrop::Get(close_button.get())
      ->SetBaseColor(kColorTabSearchButtonCRForegroundFrameActive);

  auto ink_drop_highlight_path =
      std::make_unique<views::CircleHighlightPathGenerator>(gfx::Insets());
  views::HighlightPathGenerator::Install(close_button.get(),
                                         std::move(ink_drop_highlight_path));

  close_button->SetPreferredSize(gfx::Size(kCloseButtonSize, kCloseButtonSize));
  close_button->SetBorder(nullptr);

  const gfx::Insets margin =
      gfx::Insets().set_left_right(kCloseButtonMargin, kCloseButtonMargin);
  close_button->SetProperty(views::kMarginsKey, margin);

  close_button_ = AddChildView(std::move(close_button));
  SetIsShowingNudge(false);
}

BrowserFrameView* ToolbarGlicButton::GetBrowserFrameView() const {
  BrowserView* const browser_view =
      BrowserView::GetBrowserViewForBrowser(browser_window_interface_);
  // 'browser_view' can be null during startup before the BrowserView is added
  // to a widget and is associated to `browser_window_interface_`
  if (!browser_view) {
    return nullptr;
  }

  return browser_view->browser_widget()->GetFrameView();
}

ui::ColorId ToolbarGlicButton::GetBackgroundColor() {
  std::optional<SkColor> background = ToolbarButton::GetBackgroundColor();
  return background.value_or(kColorToolbarButtonBackgroundHighlightedDefault);
}

void ToolbarGlicButton::Collapse() {
  SetInternalPadding(gfx::Insets::TLBR(0, 0, 0, kSpaceBetweenButtons));
  GlicButton<ToolbarButton>::Collapse();
}

void ToolbarGlicButton::Expand() {
  SetInternalPadding(gfx::Insets());
  GlicButton<ToolbarButton>::Expand();
}

void ToolbarGlicButton::OnBoundsChanged(const gfx::Rect& previous_bounds) {
  GlicButton<ToolbarButton>::OnBoundsChanged(previous_bounds);

  // Button layout is kPreferredSnapToMinimum, so if the width is smaller than
  // the normal width or if the button is collapsed, the label will be hidden.
  bool should_hide_label =
      width() < normal_width() || width_state() == WidthState::kCollapsed;

  auto* image_view = static_cast<views::ImageView*>(image_container_view());
  auto* box_layout = static_cast<views::BoxLayout*>(GetLayoutManager());

  if (should_hide_label) {
    if (label()->GetVisible()) {
      label()->SetVisible(false);
      image_view->SetProperty(views::kMarginsKey, gfx::Insets());
      box_layout->set_main_axis_alignment(
          views::BoxLayout::MainAxisAlignment::kCenter);
    }
  } else {
    if (!label()->GetVisible()) {
      label()->SetVisible(true);
      image_view->SetProperty(
          views::kMarginsKey,
          gfx::Insets().set_left(kIconToolbarButtonLeftMargin));
      box_layout->set_main_axis_alignment(
          views::BoxLayout::MainAxisAlignment::kCenter);
    }
  }
}

bool ToolbarGlicButton::GetIsShowingNudge() const {
  return width_state_ == WidthState::kNudge;
}

void ToolbarGlicButton::ResetSplitButtonCornerStyling() {
  SetLeftRightCornerRadii(GetRoundedCornerRadius(), GetRoundedCornerRadius());
}

float ToolbarGlicButton::GetWidthFactor() const {
  return width_factor_;
}
void ToolbarGlicButton::SetWidthFactor(float factor) {
  width_factor_ = factor;
  this->PreferredSizeChanged();
}

ui::ColorId ToolbarGlicButton::GetCustomThemeForegroundId() const {
  return kColorAvatarButtonHighlightDefaultForeground;
}

std::optional<SkColor> ToolbarGlicButton::GetHighlightTextColor() const {
  if (ShouldApplyCustomThemeFallback() && GetColorProvider()) {
    return GetColorProvider()->GetColor(
        kColorAvatarButtonHighlightDefaultForeground);
  }
  return GlicButton<ToolbarButton>::GetHighlightTextColor();
}

void ToolbarGlicButton::OnThemeChanged() {
  bool show_before_avatar =
      base::FeatureList::IsEnabled(features::kGlicToolbarButtonLocation) &&
      features::kGlicToolbarButtonLocationParam.Get() ==
          features::GlicToolbarButtonLocation::kLeftOfProfileChip;
  if (ShouldApplyCustomThemeFallback()) {
    SetDefaultBackgroundColorId(kColorAvatarButtonHighlightDefault);
  } else {
    SetDefaultBackgroundColorId(show_before_avatar
                                    ? kColorToolbar
                                    : kColorToolbarGlicButtonBackgroundDefault);
  }
  ToolbarButton::OnThemeChanged();
}

BEGIN_METADATA(ToolbarGlicButton)
END_METADATA
}  // namespace glic
