// Copyright 2023 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/power/power_button_menu_curtain_view.h"

#include <memory>

#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_id.h"
#include "ash/style/system_shadow.h"
#include "ash/system/power/power_button_menu_view_util.h"
#include "base/check_deref.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/ui/vector_icons/vector_icons.h"
#include "ui/accessibility/ax_enums.mojom-shared.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/color/color_provider.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/background.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/highlight_border.h"
#include "ui/views/layout/flex_layout_types.h"
#include "ui/views/layout/flex_layout_view.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/style/typography.h"
#include "ui/views/view_class_properties.h"

namespace ash {

namespace {

using views::Builder;
using views::FlexLayoutView;
using views::ImageView;
using views::LayoutOrientation;

constexpr gfx::Size kEnterpriseIconSize(20, 20);

// Bottom margin for the enterprise icon.
constexpr int kIconBottomMargin = 30;

// Preferred width of the dialog.
constexpr int kWidth = 400;

// Inner padding for the widget.
constexpr int kHorizontalPadding = 25;
constexpr int kVerticalPadding = 20;

// Bottom margin for the widget title.
constexpr int kTitleBottomMargin = 35;

// Line height for the widget content text.
constexpr int kContentLineHeight = 12;

gfx::ImageSkia EnterpriseIcon(const ui::ColorProvider& color_provider) {
  return gfx::CreateVectorIcon(
      chromeos::kEnterpriseIcon,
      color_provider.GetColor(kColorAshIconColorPrimary));
}

std::u16string TitleText() {
  return l10n_util::GetStringUTF16(IDS_ASH_CURTAIN_POWER_WIDGET_TITLE);
}

std::u16string MessageText() {
  return l10n_util::GetStringUTF16(IDS_ASH_CURTAIN_POWER_WIDGET_DESCRIPTION);
}

}  // namespace

PowerButtonMenuCurtainView::PowerButtonMenuCurtainView() {
  SetPaintToLayer();
  SetBorder(std::make_unique<views::HighlightBorder>(
      kPowerButtonMenuCornerRadius, kPowerButtonMenuBorderType));

  const ui::ColorId background_color_id =
      chromeos::features::IsSystemBlurEnabled()
          ? static_cast<ui::ColorId>(kPowerButtonMenuBackgroundColorId)
          : cros_tokens::kCrosSysSystemOnBaseOpaque;
  SetBackground(views::CreateSolidBackground(background_color_id));

  layer()->SetRoundedCornerRadius(
      gfx::RoundedCornersF(kPowerButtonMenuCornerRadius));
  layer()->SetIsFastRoundedCorner(true);
  if (chromeos::features::IsSystemBlurEnabled()) {
    layer()->SetBackgroundBlur(ColorProvider::kBackgroundBlurSigma);
    layer()->SetBackdropFilterQuality(ColorProvider::kBackgroundBlurQuality);
    layer()->SetFillsBoundsOpaquely(false);
  }

  GetViewAccessibility().SetRole(ax::mojom::Role::kDialog);
  Initialize();

  // Create a system shadow for current view.
  shadow_ = ash::SystemShadow::CreateShadowOnNinePatchLayerForView(
      this, ash::SystemShadow::Type::kElevation12);
  shadow_->SetRoundedCorners(
      gfx::RoundedCornersF(kPowerButtonMenuCornerRadius));
}

PowerButtonMenuCurtainView::~PowerButtonMenuCurtainView() = default;

void PowerButtonMenuCurtainView::ScheduleShowHideAnimation(bool show) {
  // Set initial state.
  SetVisible(true);

  // Calculate transform of menu view and shadow bounds.
  gfx::Transform transform;
  if (show) {
    transform.Translate(0, kPowerButtonMenuTransformDistanceDp);
  }

  SetLayerAnimation(layer(), this, show, transform);
  SetLayerAnimation(shadow_->GetLayer(), nullptr, show, transform);
}

void PowerButtonMenuCurtainView::OnThemeChanged() {
  views::View::OnThemeChanged();
  const ui::ColorProvider& color_provider = CHECK_DEREF(GetColorProvider());
  enterprise_icon().SetImage(
      ui::ImageModel::FromImageSkia(EnterpriseIcon(color_provider)));
  title_text().SetEnabledColor(
      color_provider.GetColor(kColorAshIconColorPrimary));
  description_text().SetEnabledColor(
      color_provider.GetColor(kColorAshIconColorPrimary));
}

void PowerButtonMenuCurtainView::Initialize() {
  Builder<FlexLayoutView>(this)
      .SetOrientation(LayoutOrientation::kVertical)
      .AddChildren(
          // Enterprise icon
          Builder<ImageView>()
              .SetImageSize(kEnterpriseIconSize)
              .SetSize(kEnterpriseIconSize)
              .SetHorizontalAlignment(ImageView::Alignment::kLeading)
              .SetProperty(
                  views::kMarginsKey,
                  gfx::Insets::TLBR(kVerticalPadding, kHorizontalPadding,
                                    kIconBottomMargin, kHorizontalPadding))
              .CopyAddressTo(&enterprise_icon_),
          // Title
          Builder<views::Label>()
              .SetText(TitleText())
              .SetTextStyle(views::style::STYLE_EMPHASIZED)
              .SetTextContext(views::style::CONTEXT_DIALOG_TITLE)
              .SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT)
              .SetMultiLine(true)
              .SetProperty(
                  views::kMarginsKey,
                  gfx::Insets::TLBR(0, kHorizontalPadding, kTitleBottomMargin,
                                    kHorizontalPadding))
              .SetMaximumWidth(kWidth)
              .CopyAddressTo(&title_text_),
          // Description
          Builder<views::Label>()
              .SetText(MessageText())
              .SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT)
              .SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT)
              .SetMultiLine(true)
              .SetProperty(views::kFlexBehaviorKey,
                           views::FlexSpecification(
                               views::MinimumFlexSizeRule::kPreferred,
                               views::MaximumFlexSizeRule::kUnbounded)
                               .WithWeight(1))
              .SetProperty(
                  views::kMarginsKey,
                  gfx::Insets::TLBR(0, kHorizontalPadding, kVerticalPadding,
                                    kHorizontalPadding))
              .SetLineHeight(kContentLineHeight)
              .SetMaximumWidth(kWidth)
              .CopyAddressTo(&description_text_))
      .BuildChildren();
}

void PowerButtonMenuCurtainView::OnImplicitAnimationsCompleted() {
  if (layer()->opacity() == 0.f) {
    SetVisible(false);
  }
}

BEGIN_METADATA(PowerButtonMenuCurtainView)
END_METADATA

}  // namespace ash
