// Copyright 2014 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 "printing/print_settings_conversion.h"

#include <stddef.h>

#include <algorithm>
#include <cmath>
#include <memory>
#include <string>
#include <utility>

#include "base/containers/contains.h"
#include "base/containers/fixed_flat_set.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "printing/mojom/print.mojom.h"
#include "printing/print_job_constants.h"
#include "printing/print_settings.h"
#include "printing/units.h"

namespace printing {

namespace {

// Note: If this code crashes, then the caller has passed in invalid `settings`.
// Fix the caller, instead of trying to avoid the crash here.
PageMargins GetCustomMarginsFromJobSettings(const base::Value::Dict& settings) {
  PageMargins margins_in_points;
  const base::Value::Dict* custom_margins =
      settings.FindDict(kSettingMarginsCustom);
  margins_in_points.top = custom_margins->FindInt(kSettingMarginTop).value();
  margins_in_points.bottom =
      custom_margins->FindInt(kSettingMarginBottom).value();
  margins_in_points.left = custom_margins->FindInt(kSettingMarginLeft).value();
  margins_in_points.right =
      custom_margins->FindInt(kSettingMarginRight).value();
  return margins_in_points;
}

void SetMarginsToJobSettings(const std::string& json_path,
                             const PageMargins& margins,
                             base::Value::Dict& job_settings) {
  base::Value::Dict dict;
  dict.Set(kSettingMarginTop, margins.top);
  dict.Set(kSettingMarginBottom, margins.bottom);
  dict.Set(kSettingMarginLeft, margins.left);
  dict.Set(kSettingMarginRight, margins.right);
  job_settings.Set(json_path, std::move(dict));
}

void SetSizeToJobSettings(const std::string& json_path,
                          const gfx::Size& size,
                          base::Value::Dict& job_settings) {
  base::Value::Dict dict;
  dict.Set("width", size.width());
  dict.Set("height", size.height());
  job_settings.Set(json_path, std::move(dict));
}

void SetRectToJobSettings(const std::string& json_path,
                          const gfx::Rect& rect,
                          base::Value::Dict& job_settings) {
  base::Value::Dict dict;
  dict.Set("x", rect.x());
  dict.Set("y", rect.y());
  dict.Set("width", rect.width());
  dict.Set("height", rect.height());
  job_settings.Set(json_path, std::move(dict));
}

}  // namespace

PageRanges GetPageRangesFromJobSettings(const base::Value::Dict& job_settings) {
  PageRanges page_ranges;
  const base::Value::List* page_range_array =
      job_settings.FindList(kSettingPageRange);
  if (!page_range_array)
    return page_ranges;

  for (const base::Value& page_range : *page_range_array) {
    if (!page_range.is_dict())
      continue;

    const auto& dict = page_range.GetDict();
    absl::optional<int> from = dict.FindInt(kSettingPageRangeFrom);
    absl::optional<int> to = dict.FindInt(kSettingPageRangeTo);
    if (!from.has_value() || !to.has_value())
      continue;

    // Page numbers are 1-based in the dictionary.
    // Page numbers are 0-based for the printing context.
    page_ranges.push_back(PageRange{static_cast<uint32_t>(from.value() - 1),
                                    static_cast<uint32_t>(to.value() - 1)});
  }
  return page_ranges;
}

std::unique_ptr<PrintSettings> PrintSettingsFromJobSettings(
    const base::Value::Dict& job_settings) {
  auto settings = std::make_unique<PrintSettings>();
  absl::optional<bool> display_header_footer =
      job_settings.FindBool(kSettingHeaderFooterEnabled);
  if (!display_header_footer.has_value())
    return nullptr;

  settings->set_display_header_footer(display_header_footer.value());
  if (settings->display_header_footer()) {
    const std::string* title =
        job_settings.FindString(kSettingHeaderFooterTitle);
    const std::string* url = job_settings.FindString(kSettingHeaderFooterURL);
    if (!title || !url)
      return nullptr;

    settings->set_title(base::UTF8ToUTF16(*title));
    settings->set_url(base::UTF8ToUTF16(*url));
  }

  absl::optional<bool> backgrounds =
      job_settings.FindBool(kSettingShouldPrintBackgrounds);
  absl::optional<bool> selection_only =
      job_settings.FindBool(kSettingShouldPrintSelectionOnly);
  if (!backgrounds.has_value() || !selection_only.has_value())
    return nullptr;

  settings->set_should_print_backgrounds(backgrounds.value());
  settings->set_selection_only(selection_only.value());

  absl::optional<bool> collate = job_settings.FindBool(kSettingCollate);
  absl::optional<int> copies = job_settings.FindInt(kSettingCopies);
  absl::optional<int> color = job_settings.FindInt(kSettingColor);
  absl::optional<int> duplex_mode = job_settings.FindInt(kSettingDuplexMode);
  absl::optional<bool> landscape = job_settings.FindBool(kSettingLandscape);
  absl::optional<int> scale_factor = job_settings.FindInt(kSettingScaleFactor);
  absl::optional<bool> rasterize_pdf =
      job_settings.FindBool(kSettingRasterizePdf);
  absl::optional<int> pages_per_sheet =
      job_settings.FindInt(kSettingPagesPerSheet);
  if (!collate.has_value() || !copies.has_value() || !color.has_value() ||
      !duplex_mode.has_value() || !landscape.has_value() ||
      !scale_factor.has_value() || !rasterize_pdf.has_value() ||
      !pages_per_sheet.has_value()) {
    return nullptr;
  }
  settings->set_collate(collate.value());
  settings->set_copies(copies.value());
  settings->SetOrientation(landscape.value());
  settings->set_device_name(
      base::UTF8ToUTF16(*job_settings.FindString(kSettingDeviceName)));
  settings->set_duplex_mode(
      static_cast<mojom::DuplexMode>(duplex_mode.value()));
  settings->set_color(static_cast<mojom::ColorModel>(color.value()));
  settings->set_scale_factor(static_cast<double>(scale_factor.value()) / 100.0);
  settings->set_rasterize_pdf(rasterize_pdf.value());
  settings->set_pages_per_sheet(pages_per_sheet.value());

  absl::optional<int> dpi_horizontal =
      job_settings.FindInt(kSettingDpiHorizontal);
  absl::optional<int> dpi_vertical = job_settings.FindInt(kSettingDpiVertical);
  if (!dpi_horizontal.has_value() || !dpi_vertical.has_value())
    return nullptr;

  settings->set_dpi_xy(dpi_horizontal.value(), dpi_vertical.value());

  absl::optional<int> rasterize_pdf_dpi =
      job_settings.FindInt(kSettingRasterizePdfDpi);
  if (rasterize_pdf_dpi.has_value())
    settings->set_rasterize_pdf_dpi(rasterize_pdf_dpi.value());

  PrintSettings::RequestedMedia requested_media;
  const base::Value::Dict* media_size_value =
      job_settings.FindDict(kSettingMediaSize);
  if (media_size_value) {
    absl::optional<int> width_microns =
        media_size_value->FindInt(kSettingMediaSizeWidthMicrons);
    absl::optional<int> height_microns =
        media_size_value->FindInt(kSettingMediaSizeHeightMicrons);
    if (width_microns.has_value() && height_microns.has_value()) {
      requested_media.size_microns =
          gfx::Size(width_microns.value(), height_microns.value());
    }

    const std::string* vendor_id =
        media_size_value->FindString(kSettingMediaSizeVendorId);
    if (vendor_id && !vendor_id->empty())
      requested_media.vendor_id = *vendor_id;
  }
  settings->set_requested_media(requested_media);

  mojom::MarginType margin_type = static_cast<mojom::MarginType>(
      job_settings.FindInt(kSettingMarginsType)
          .value_or(static_cast<int>(mojom::MarginType::kDefaultMargins)));
  if (margin_type != mojom::MarginType::kDefaultMargins &&
      margin_type != mojom::MarginType::kNoMargins &&
      margin_type != mojom::MarginType::kCustomMargins &&
      margin_type != mojom::MarginType::kPrintableAreaMargins) {
    margin_type = mojom::MarginType::kDefaultMargins;
  }
  settings->set_margin_type(margin_type);

  if (margin_type == mojom::MarginType::kCustomMargins)
    settings->SetCustomMargins(GetCustomMarginsFromJobSettings(job_settings));

  settings->set_ranges(GetPageRangesFromJobSettings(job_settings));

  absl::optional<bool> is_modifiable =
      job_settings.FindBool(kSettingPreviewModifiable);
  if (is_modifiable.has_value()) {
    settings->set_is_modifiable(is_modifiable.value());
  }

#if BUILDFLAG(IS_CHROMEOS) || (BUILDFLAG(IS_LINUX) && defined(USE_CUPS))
  const base::Value::Dict* advanced_settings =
      job_settings.FindDict(kSettingAdvancedSettings);
  if (advanced_settings) {
    for (const auto item : *advanced_settings) {
      static constexpr auto kNonJobAttributes =
          base::MakeFixedFlatSet<base::StringPiece>(
              {"printer-info", "printer-make-and-model", "system_driverinfo"});
      if (!base::Contains(kNonJobAttributes, item.first))
        settings->advanced_settings().emplace(item.first, item.second.Clone());
    }
  }
#endif  // BUILDFLAG(IS_CHROMEOS) || (BUILDFLAG(IS_LINUX) && defined(USE_CUPS))

#if BUILDFLAG(IS_CHROMEOS)
  bool send_user_info =
      job_settings.FindBool(kSettingSendUserInfo).value_or(false);
  settings->set_send_user_info(send_user_info);
  if (send_user_info) {
    const std::string* username = job_settings.FindString(kSettingUsername);
    if (username)
      settings->set_username(*username);
  }

  const std::string* pin_value = job_settings.FindString(kSettingPinValue);
  if (pin_value)
    settings->set_pin_value(*pin_value);
#endif  // BUILDFLAG(IS_CHROMEOS)

  return settings;
}

base::Value::Dict PrintSettingsToJobSettingsDebug(
    const PrintSettings& settings) {
  base::Value::Dict job_settings;

  job_settings.Set(kSettingHeaderFooterEnabled,
                   settings.display_header_footer());
  job_settings.Set(kSettingHeaderFooterTitle, settings.title());
  job_settings.Set(kSettingHeaderFooterURL, settings.url());
  job_settings.Set(kSettingShouldPrintBackgrounds,
                   settings.should_print_backgrounds());
  job_settings.Set(kSettingShouldPrintSelectionOnly, settings.selection_only());
  job_settings.Set(kSettingMarginsType,
                   static_cast<int>(settings.margin_type()));
  if (!settings.ranges().empty()) {
    base::Value::List page_range_array;
    for (const auto& range : settings.ranges()) {
      base::Value::Dict dict;
      dict.Set(kSettingPageRangeFrom, static_cast<int>(range.from + 1));
      dict.Set(kSettingPageRangeTo, static_cast<int>(range.to + 1));
      page_range_array.Append(std::move(dict));
    }
    job_settings.Set(kSettingPageRange, std::move(page_range_array));
  }

  job_settings.Set(kSettingCollate, settings.collate());
  job_settings.Set(kSettingCopies, settings.copies());
  job_settings.Set(kSettingColor, static_cast<int>(settings.color()));
  job_settings.Set(kSettingDuplexMode,
                   static_cast<int>(settings.duplex_mode()));
  job_settings.Set(kSettingLandscape, settings.landscape());
  job_settings.Set(kSettingDeviceName, settings.device_name());
  job_settings.Set(kSettingDpiHorizontal, settings.dpi_horizontal());
  job_settings.Set(kSettingDpiVertical, settings.dpi_vertical());
  job_settings.Set(kSettingScaleFactor,
                   static_cast<int>((settings.scale_factor() * 100.0) + 0.5));
  job_settings.Set(kSettingRasterizePdf, settings.rasterize_pdf());
  job_settings.Set(kSettingPagesPerSheet, settings.pages_per_sheet());

  // Following values are not read form JSON by InitSettings, so do not have
  // common public constants. So just serialize in "debug" section.
  base::Value::Dict debug;
  debug.Set("dpi", settings.dpi());
  debug.Set("deviceUnitsPerInch", settings.device_units_per_inch());
  debug.Set("support_alpha_blend", settings.should_print_backgrounds());
  debug.Set("media_vendor_id", settings.requested_media().vendor_id);
  SetSizeToJobSettings("media_size", settings.requested_media().size_microns,
                       debug);
  SetMarginsToJobSettings("requested_custom_margins_in_points",
                          settings.requested_custom_margins_in_points(), debug);
  const PageSetup& page_setup = settings.page_setup_device_units();
  SetMarginsToJobSettings("effective_margins", page_setup.effective_margins(),
                          debug);
  SetSizeToJobSettings("physical_size", page_setup.physical_size(), debug);
  SetRectToJobSettings("overlay_area", page_setup.overlay_area(), debug);
  SetRectToJobSettings("content_area", page_setup.content_area(), debug);
  SetRectToJobSettings("printable_area", page_setup.printable_area(), debug);
  job_settings.Set("debug", std::move(debug));

  return job_settings;
}

}  // namespace printing
