// Copyright 2025 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/download/status_text_builder_utils.h"

#include <string>

#include "base/byte_size.h"
#include "base/i18n/rtl.h"
#include "chrome/grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/text/bytes_formatting.h"

namespace {

// Concatenates the `bytes_substring` and `detail_message` with a separator.
// Ex: "100/120 MB • Opening in 10 seconds..."
// If `is_download_active` is true, then the `bytes_substring` is prefixed with
// a down arrow symbol. Ex: "↓ 100/120 MB • Opening in 10 seconds..."
std::u16string BuildBubbleStatusMessageWithBytes(
    const std::u16string& bytes_substring,
    const std::u16string& detail_message,
    bool is_download_active) {
  // For some RTL languages (e.g. Hebrew), the translated form of 123/456 MB
  // still uses the English characters "MB" rather than RTL characters. We
  // specifically mark this as LTR because it should be displayed as "123/456
  // MB" (not "MB 123/456"). Conversely, some other RTL languages (e.g. Arabic)
  // do translate "MB" to RTL characters. For these, we do nothing, that way the
  // phrase is correctly displayed as RTL, with the translated "MB" to the left
  // of the fraction.
  std::u16string text;
  if (base::i18n::GetStringDirection(bytes_substring) ==
      base::i18n::TextDirection::LEFT_TO_RIGHT) {
    text = base::i18n::GetDisplayStringInLTRDirectionality(bytes_substring);
  } else {
    text = bytes_substring;
  }

  if (is_download_active) {
    text = l10n_util::GetStringFUTF16(
        IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_WITH_SYMBOL, text);
  }

  text = l10n_util::GetStringFUTF16(
      IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_MESSAGE_WITH_SEPARATOR, text,
      detail_message);

  // Some RTL languages like Hebrew still display "MB" in English
  // characters, which are the first strongly directional characters in
  // the full string. We mark the full string as RTL to ensure it doesn't get
  // displayed as LTR in spite of the first characters ("MB") being LTR.
  base::i18n::AdjustStringForLocaleDirection(&text);
  return text;
}

}  // namespace

// static
std::u16string
StatusTextBuilderUtils::GetActiveDownloadBubbleStatusMessageWithBytes(
    const std::u16string& bytes_substring,
    const std::u16string& detail_message) {
  return BuildBubbleStatusMessageWithBytes(bytes_substring, detail_message,
                                           /*is_download_active=*/true);
}

// static
std::u16string StatusTextBuilderUtils::GetBubbleStatusMessageWithBytes(
    const std::u16string& bytes_substring,
    const std::u16string& detail_message) {
  return BuildBubbleStatusMessageWithBytes(bytes_substring, detail_message,
                                           /*is_download_active=*/false);
}

// static
std::u16string StatusTextBuilderUtils::GetCompletedTotalSizeString(
    int64_t total_bytes) {
  return GetBubbleStatusMessageWithBytes(
      ui::FormatBytes(
          base::ByteSize(base::checked_cast<uint64_t>(total_bytes))),
      l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_STATUS_DONE));
}

// static
std::u16string StatusTextBuilderUtils::GetBubbleProgressSizesString(
    int64_t completed_bytes,
    int64_t total_bytes) {
  base::ByteSize size =
      base::ByteSize(base::checked_cast<uint64_t>(completed_bytes));
  base::ByteSize total =
      base::ByteSize(base::checked_cast<uint64_t>(total_bytes));
  if (total.is_positive()) {
    ui::DataUnits amount_units = ui::GetByteDisplayUnits(total);
    std::u16string simple_size =
        ui::FormatBytesWithUnits(size, amount_units, false);
    std::u16string simple_total =
        ui::FormatBytesWithUnits(total, amount_units, true);

    // Linux prepends an RLM (right-to-left mark) in the FormatBytesWithUnits
    // call when showing units if the string has strong RTL characters. This is
    // problematic for this fraction use case because it ends up moving it
    // around so that the numerator is in the wrong place. Therefore, we remove
    // that extra marker before proceeding.
    base::i18n::UnadjustStringForLocaleDirection(&simple_total);
    return l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_SIZES, simple_size,
                                      simple_total);
  }
  return ui::FormatBytes(size);
}
