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

#include "chrome/browser/notifications/notification_template_builder.h"

#include <algorithm>

#include "base/files/file_path.h"
#include "base/i18n/time_formatting.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chrome/browser/notifications/notification_image_retainer.h"
#include "chrome/grit/chromium_strings.h"
#include "components/url_formatter/elide_url.h"
#include "third_party/libxml/chromium/libxml_utils.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/message_center/notification.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace {

// Constants used for the XML element names and their attributes.
const char kActionElement[] = "action";
const char kActionsElement[] = "actions";
const char kActivationType[] = "activationType";
const char kArguments[] = "arguments";
const char kAttribution[] = "attribution";
const char kAudioElement[] = "audio";
const char kBindingElement[] = "binding";
const char kBindingElementTemplateAttribute[] = "template";
const char kContent[] = "content";
const char kContextMenu[] = "contextMenu";
const char kForeground[] = "foreground";
const char kHero[] = "hero";
const char kHintCrop[] = "hint-crop";
const char kHintCropNone[] = "none";
const char kImageElement[] = "image";
const char kImageUri[] = "imageUri";
const char kInputElement[] = "input";
const char kInputId[] = "id";
const char kInputType[] = "type";
const char kStatus[] = "status";
const char kNotificationSettings[] = "notificationSettings";
const char kPlaceholderContent[] = "placeHolderContent";
const char kPlacement[] = "placement";
const char kPlacementAppLogoOverride[] = "appLogoOverride";
const char kProgress[] = "progress";
const char kReminder[] = "reminder";
const char kScenario[] = "scenario";
const char kSilent[] = "silent";
const char kSrc[] = "src";
const char kText[] = "text";
const char kTextElement[] = "text";
const char kToastElementDisplayTimestamp[] = "displayTimestamp";
const char kTrue[] = "true";
const char kUserResponse[] = "userResponse";
const char kValue[] = "value";
const char kVisualElement[] = "visual";

// Name of the template used for default Chrome notifications.
const char kDefaultTemplate[] = "ToastGeneric";

// The XML version header that has to be stripped from the output.
const char kXmlVersionHeader[] = "<?xml version=\"1.0\"?>\n";

}  // namespace

const char kNotificationButtonIndex[] = "buttonIndex";
const char kNotificationToastElement[] = "toast";
const char kNotificationLaunchAttribute[] = "launch";

// static
const char* NotificationTemplateBuilder::context_menu_label_override_ = nullptr;

// static
std::unique_ptr<NotificationTemplateBuilder> NotificationTemplateBuilder::Build(
    NotificationImageRetainer* notification_image_retainer,
    const std::string& launch_attribute,
    const std::string& profile_id,
    const message_center::Notification& notification) {
  std::unique_ptr<NotificationTemplateBuilder> builder = base::WrapUnique(
      new NotificationTemplateBuilder(notification_image_retainer, profile_id));

  builder->StartToastElement(launch_attribute, notification);
  builder->StartVisualElement();

  builder->StartBindingElement(kDefaultTemplate);

  // Content for the toast template.
  builder->WriteTextElement(base::UTF16ToUTF8(notification.title()),
                            TextType::NORMAL);

  // Message has historically not been shown for list-style notifications.
  if (notification.type() == message_center::NOTIFICATION_TYPE_MULTIPLE &&
      !notification.items().empty()) {
    builder->WriteItems(notification.items());
  } else {
    builder->WriteTextElement(base::UTF16ToUTF8(notification.message()),
                              TextType::NORMAL);
  }

  std::string attribution;
  if (notification.UseOriginAsContextMessage())
    attribution = builder->FormatOrigin(notification.origin_url());
  else if (!notification.context_message().empty())
    attribution = base::UTF16ToUTF8(notification.context_message());

  if (!attribution.empty())
    builder->WriteTextElement(attribution, TextType::ATTRIBUTION);

  if (!notification.icon().IsEmpty())
    builder->WriteIconElement(notification);

  if (!notification.image().IsEmpty())
    builder->WriteLargeImageElement(notification);

  if (notification.type() == message_center::NOTIFICATION_TYPE_PROGRESS)
    builder->WriteProgressElement(notification);

  builder->EndBindingElement();
  builder->EndVisualElement();

  builder->StartActionsElement();
  if (!notification.buttons().empty())
    builder->AddActions(notification);
  builder->AddContextMenu();
  builder->EndActionsElement();

  if (notification.silent())
    builder->WriteAudioSilentElement();

  builder->EndToastElement();

  return builder;
}

NotificationTemplateBuilder::NotificationTemplateBuilder(
    NotificationImageRetainer* notification_image_retainer,
    const std::string& profile_id)
    : xml_writer_(std::make_unique<XmlWriter>()),
      image_retainer_(notification_image_retainer),
      profile_id_(profile_id) {
  xml_writer_->StartWriting();
}

NotificationTemplateBuilder::~NotificationTemplateBuilder() = default;

base::string16 NotificationTemplateBuilder::GetNotificationTemplate() const {
  std::string template_xml = xml_writer_->GetWrittenString();
  DCHECK(base::StartsWith(template_xml, kXmlVersionHeader,
                          base::CompareCase::SENSITIVE));

  // The |kXmlVersionHeader| is automatically appended by libxml, but the toast
  // system in the Windows Action Center expects it to be absent.
  return base::UTF8ToUTF16(template_xml.substr(sizeof(kXmlVersionHeader) - 1));
}

std::string NotificationTemplateBuilder::FormatOrigin(
    const GURL& origin) const {
  base::string16 origin_string = url_formatter::FormatOriginForSecurityDisplay(
      url::Origin::Create(origin),
      url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
  DCHECK(origin_string.size());

  return base::UTF16ToUTF8(origin_string);
}

void NotificationTemplateBuilder::StartToastElement(
    const std::string& launch_attribute,
    const message_center::Notification& notification) {
  xml_writer_->StartElement(kNotificationToastElement);
  xml_writer_->AddAttribute(kNotificationLaunchAttribute, launch_attribute);

  // Note: If the notification doesn't include a button, then Windows will
  // ignore the Reminder flag.
  if (notification.never_timeout())
    xml_writer_->AddAttribute(kScenario, kReminder);

  if (notification.timestamp().is_null())
    return;

  base::Time::Exploded exploded;
  notification.timestamp().UTCExplode(&exploded);
  xml_writer_->AddAttribute(
      kToastElementDisplayTimestamp,
      base::StringPrintf("%04d-%02d-%02dT%02d:%02d:%02dZ", exploded.year,
                         exploded.month, exploded.day_of_month, exploded.hour,
                         exploded.minute, exploded.second));
}

void NotificationTemplateBuilder::EndToastElement() {
  xml_writer_->EndElement();
  xml_writer_->StopWriting();
}

void NotificationTemplateBuilder::StartVisualElement() {
  xml_writer_->StartElement(kVisualElement);
}

void NotificationTemplateBuilder::EndVisualElement() {
  xml_writer_->EndElement();
}

void NotificationTemplateBuilder::StartBindingElement(
    const std::string& template_name) {
  xml_writer_->StartElement(kBindingElement);
  xml_writer_->AddAttribute(kBindingElementTemplateAttribute, template_name);
}

void NotificationTemplateBuilder::EndBindingElement() {
  xml_writer_->EndElement();
}

void NotificationTemplateBuilder::WriteTextElement(const std::string& content,
                                                   TextType text_type) {
  xml_writer_->StartElement(kTextElement);
  if (text_type == TextType::ATTRIBUTION)
    xml_writer_->AddAttribute(kPlacement, kAttribution);
  xml_writer_->AppendElementContent(content);
  xml_writer_->EndElement();
}

void NotificationTemplateBuilder::WriteItems(
    const std::vector<message_center::NotificationItem>& items) {
  // A toast can have a maximum of three text items, of which one is reserved
  // for the title. The remaining two can each handle up to four lines of text,
  // but the toast can only show four lines total, so there's no point in having
  // more than one text item. Therefore, we show them all in one and hope there
  // is no truncation at the bottom. There will never be room for items 5 and up
  // so we don't make an attempt to show them.
  constexpr size_t kMaxEntries = 4;
  size_t entries = std::min(kMaxEntries, items.size());
  std::string item_list;
  for (size_t i = 0; i < entries; ++i) {
    const auto& item = items[i];
    item_list += base::UTF16ToUTF8(item.title) + " - " +
                 base::UTF16ToUTF8(item.message) + "\n";
  }
  WriteTextElement(item_list, TextType::NORMAL);
}

void NotificationTemplateBuilder::WriteIconElement(
    const message_center::Notification& notification) {
  WriteImageElement(notification.icon(), notification.origin_url(),
                    kPlacementAppLogoOverride, kHintCropNone);
}

void NotificationTemplateBuilder::WriteLargeImageElement(
    const message_center::Notification& notification) {
  WriteImageElement(notification.image(), notification.origin_url(), kHero,
                    std::string());
}

void NotificationTemplateBuilder::WriteImageElement(
    const gfx::Image& image,
    const GURL& origin,
    const std::string& placement,
    const std::string& hint_crop) {
  base::FilePath path =
      image_retainer_->RegisterTemporaryImage(image, profile_id_, origin);
  if (!path.empty()) {
    xml_writer_->StartElement(kImageElement);
    xml_writer_->AddAttribute(kPlacement, placement);
    xml_writer_->AddAttribute(kSrc, base::UTF16ToUTF8(path.value()));
    if (!hint_crop.empty())
      xml_writer_->AddAttribute(kHintCrop, hint_crop);
    xml_writer_->EndElement();
  }
}

void NotificationTemplateBuilder::WriteProgressElement(
    const message_center::Notification& notification) {
  // Two other attributes are supported by Microsoft:
  // title: A string shown on the left side of the toast, just above the bar.
  // valueStringOverride: A string that replaces the percentage on the right.
  xml_writer_->StartElement(kProgress);
  // Status is mandatory, without it the progress bar is not shown.
  xml_writer_->AddAttribute(kStatus, std::string());
  xml_writer_->AddAttribute(
      kValue, base::StringPrintf("%3.2f", 1.0 * notification.progress() / 100));
  xml_writer_->EndElement();
}

void NotificationTemplateBuilder::AddActions(
    const message_center::Notification& notification) {
  const std::vector<message_center::ButtonInfo>& buttons =
      notification.buttons();
  bool inline_reply = false;
  std::string placeholder;
  for (const auto& button : buttons) {
    if (button.type != message_center::ButtonType::TEXT)
      continue;

    inline_reply = true;
    placeholder = base::UTF16ToUTF8(button.placeholder);
    break;
  }

  if (inline_reply) {
    xml_writer_->StartElement(kInputElement);
    xml_writer_->AddAttribute(kInputId, kUserResponse);
    xml_writer_->AddAttribute(kInputType, kText);
    xml_writer_->AddAttribute(kPlaceholderContent, placeholder);
    xml_writer_->EndElement();
  }

  for (size_t i = 0; i < buttons.size(); ++i)
    WriteActionElement(buttons[i], i, notification.origin_url());
}

void NotificationTemplateBuilder::AddContextMenu() {
  std::string notification_settings_msg = l10n_util::GetStringUTF8(
      IDS_WIN_NOTIFICATION_SETTINGS_CONTEXT_MENU_ITEM_NAME);
  if (context_menu_label_override_)
    notification_settings_msg = context_menu_label_override_;
  WriteContextMenuElement(notification_settings_msg, kNotificationSettings);
}

void NotificationTemplateBuilder::StartActionsElement() {
  xml_writer_->StartElement(kActionsElement);
}

void NotificationTemplateBuilder::EndActionsElement() {
  xml_writer_->EndElement();
}

void NotificationTemplateBuilder::WriteAudioSilentElement() {
  xml_writer_->StartElement(kAudioElement);
  xml_writer_->AddAttribute(kSilent, kTrue);
  xml_writer_->EndElement();
}

void NotificationTemplateBuilder::WriteActionElement(
    const message_center::ButtonInfo& button,
    int index,
    const GURL& origin) {
  xml_writer_->StartElement(kActionElement);
  xml_writer_->AddAttribute(kActivationType, kForeground);
  xml_writer_->AddAttribute(kContent, base::UTF16ToUTF8(button.title));
  std::string param =
      std::string(kNotificationButtonIndex) + "=" + base::IntToString(index);
  xml_writer_->AddAttribute(kArguments, param);

  if (!button.icon.IsEmpty()) {
    base::FilePath path = image_retainer_->RegisterTemporaryImage(
        button.icon, profile_id_, origin);
    if (!path.empty())
      xml_writer_->AddAttribute(kImageUri, path.AsUTF8Unsafe());
  }

  xml_writer_->EndElement();
}

void NotificationTemplateBuilder::WriteContextMenuElement(
    const std::string& content,
    const std::string& arguments) {
  xml_writer_->StartElement(kActionElement);
  xml_writer_->AddAttribute(kContent, content);
  xml_writer_->AddAttribute(kPlacement, kContextMenu);
  xml_writer_->AddAttribute(kActivationType, kForeground);
  xml_writer_->AddAttribute(kArguments, arguments);
  xml_writer_->EndElement();
}

void NotificationTemplateBuilder::OverrideContextMenuLabelForTesting(
    const char* label) {
  context_menu_label_override_ = label;
}
