// Copyright 2022 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/sharing_hub/preview_view.h"

#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/sharing_hub/sharing_hub_bubble_controller.h"
#include "components/url_formatter/elide_url.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/layout/flex_layout_types.h"
#include "ui/views/view_class_properties.h"

namespace sharing_hub {

namespace {

class UrlLabel : public views::Label {
  METADATA_HEADER(UrlLabel, views::Label)

 public:
  UrlLabel(GURL url, int context, int style)
      : views::Label(base::UTF8ToUTF16(url.spec()), context, style), url_(url) {
    // Never use the elided URL for the accessible name or tooltip - both of
    // these are allowed to be of arbitrary length (since they aren't
    // constrained by the visual layout) and should give the user the full URL.
    GetViewAccessibility().SetName(std::u16string(GetText()));
    SetCustomTooltipText(GetText());
  }
  ~UrlLabel() override = default;

  void OnBoundsChanged(const gfx::Rect& previous) override {
    // Danger! Do not repurpose this behavior for your own use!
    //
    // It is safe to change the text in response to a layout like this *only*
    // because the UrlLabel is included in a fixed-width bubble. If the bubble
    // instead had variable width, or this view's width could otherwise change,
    // then it would be very easy to get into an infinite loop between setting
    // the text (thus prompting a relayout) and the layout setting the width
    // (thus causing the text to be set again). Since the bubble containing the
    // UrlLabel has a fixed width, this infinite recurrence can't happen.
    views::Label::OnBoundsChanged(previous);
    SetText(url_formatter::ElideUrl(url_, font_list(), width()));
  }

 private:
  GURL url_;
};

BEGIN_METADATA(UrlLabel)
END_METADATA

}  // namespace

// This view uses two nested FlexLayouts, a horizontal outer one and a vertical
// inner one, to create a composite layout where the icon is aligned with the
// title and URL taken together. The resulting View tree looks like this:
//   PreviewView [FlexLayout, horizontal]
//     ImageView
//     View [FlexLayout, vertical]
//       Label (title)
//       Label (URL)
PreviewView::PreviewView(share::ShareAttempt attempt) {
  // These values are all directly from the Figma redlines. See
  // https://crbug.com/40832894 and https://crbug.com/40834138.
  constexpr gfx::Insets kInteriorMargin = gfx::Insets::VH(8, 8);
  constexpr gfx::Insets kDefaultMargin = gfx::Insets::VH(0, 16);
  constexpr gfx::Size kImageSize{16, 16};

  auto* layout = SetLayoutManager(std::make_unique<views::FlexLayout>());
  layout->SetOrientation(views::LayoutOrientation::kHorizontal)
      .SetMainAxisAlignment(views::LayoutAlignment::kStart)
      .SetCrossAxisAlignment(views::LayoutAlignment::kCenter)
      .SetInteriorMargin(kInteriorMargin)
      .SetDefault(views::kMarginsKey, kDefaultMargin)
      .SetCollapseMargins(true);

  image_ =
      AddChildView(std::make_unique<views::ImageView>(attempt.preview_image));
  image_->SetPreferredSize(kImageSize);

  auto* labels_container = AddChildView(std::make_unique<views::View>());
  labels_container->SetProperty(
      views::kFlexBehaviorKey,
      views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero));
  auto* labels_layout =
      labels_container->SetLayoutManager(std::make_unique<views::FlexLayout>());
  labels_layout->SetOrientation(views::LayoutOrientation::kVertical)
      .SetMainAxisAlignment(views::LayoutAlignment::kCenter)
      .SetCrossAxisAlignment(views::LayoutAlignment::kStart)
      .SetDefault(
          views::kFlexBehaviorKey,
          views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero));

  // TODO(ellyjones): These do not exactly match the redlines, which call for
  // 14pt Roboto specifically. We should probably update the redlines to not
  // use a hardcoded font, but we could also specify the font more explicitly
  // here.
  title_ = labels_container->AddChildView(std::make_unique<views::Label>(
      attempt.title, views::style::CONTEXT_DIALOG_BODY_TEXT));
  title_->SetHorizontalAlignment(gfx::ALIGN_LEFT);

  url_ = labels_container->AddChildView(std::make_unique<UrlLabel>(
      attempt.url, views::style::CONTEXT_DIALOG_BODY_TEXT,
      views::style::STYLE_HINT));
  url_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
}

PreviewView::~PreviewView() = default;

BEGIN_METADATA(PreviewView)
END_METADATA

}  // namespace sharing_hub
