// 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/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.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& settings) {
  PageMargins margins_in_points;
  const base::Value* custom_margins = settings.FindKey(kSettingMarginsCustom);
  margins_in_points.top = custom_margins->FindIntKey(kSettingMarginTop).value();
  margins_in_points.bottom =
      custom_margins->FindIntKey(kSettingMarginBottom).value();
  margins_in_points.left =
      custom_margins->FindIntKey(kSettingMarginLeft).value();
  margins_in_points.right =
      custom_margins->FindIntKey(kSettingMarginRight).value();
  return margins_in_points;
}

void SetMarginsToJobSettings(const std::string& json_path,
                             const PageMargins& margins,
                             base::DictionaryValue* job_settings) {
  auto dict = std::make_unique<base::DictionaryValue>();
  dict->SetInteger(kSettingMarginTop, margins.top);
  dict->SetInteger(kSettingMarginBottom, margins.bottom);
  dict->SetInteger(kSettingMarginLeft, margins.left);
  dict->SetInteger(kSettingMarginRight, margins.right);
  job_settings->Set(json_path, std::move(dict));
}

void SetSizeToJobSettings(const std::string& json_path,
                          const gfx::Size& size,
                          base::DictionaryValue* job_settings) {
  auto dict = std::make_unique<base::DictionaryValue>();
  dict->SetInteger("width", size.width());
  dict->SetInteger("height", size.height());
  job_settings->Set(json_path, std::move(dict));
}

void SetRectToJobSettings(const std::string& json_path,
                          const gfx::Rect& rect,
                          base::DictionaryValue* job_settings) {
  auto dict = std::make_unique<base::DictionaryValue>();
  dict->SetInteger("x", rect.x());
  dict->SetInteger("y", rect.y());
  dict->SetInteger("width", rect.width());
  dict->SetInteger("height", rect.height());
  job_settings->Set(json_path, std::move(dict));
}

}  // namespace

bool PrintSettingsFromJobSettings(const base::Value& job_settings,
                                  PrintSettings* settings) {
  base::Optional<bool> display_header_footer =
      job_settings.FindBoolKey(kSettingHeaderFooterEnabled);
  if (!display_header_footer.has_value())
    return false;

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

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

  base::Optional<bool> backgrounds =
      job_settings.FindBoolKey(kSettingShouldPrintBackgrounds);
  base::Optional<bool> selection_only =
      job_settings.FindBoolKey(kSettingShouldPrintSelectionOnly);
  if (!backgrounds.has_value() || !selection_only.has_value())
    return false;

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

  PrintSettings::RequestedMedia requested_media;
  const base::Value* media_size_value = job_settings.FindKeyOfType(
      kSettingMediaSize, base::Value::Type::DICTIONARY);
  if (media_size_value) {
    base::Optional<int> width_microns =
        media_size_value->FindIntKey(kSettingMediaSizeWidthMicrons);
    base::Optional<int> height_microns =
        media_size_value->FindIntKey(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->FindStringKey(kSettingMediaSizeVendorId);
    if (vendor_id && !vendor_id->empty())
      requested_media.vendor_id = *vendor_id;
  }
  settings->set_requested_media(requested_media);

  int margin_type =
      job_settings.FindIntKey(kSettingMarginsType).value_or(DEFAULT_MARGINS);
  if (margin_type != DEFAULT_MARGINS && margin_type != NO_MARGINS &&
      margin_type != CUSTOM_MARGINS && margin_type != PRINTABLE_AREA_MARGINS) {
    margin_type = DEFAULT_MARGINS;
  }
  settings->set_margin_type(static_cast<MarginType>(margin_type));

  if (margin_type == CUSTOM_MARGINS)
    settings->SetCustomMargins(GetCustomMarginsFromJobSettings(job_settings));

  PageRanges new_ranges;
  const base::Value* page_range_array =
      job_settings.FindKeyOfType(kSettingPageRange, base::Value::Type::LIST);
  if (page_range_array) {
    for (const base::Value& value : page_range_array->GetList()) {
      if (!value.is_dict())
        continue;

      base::Optional<int> from = value.FindIntKey(kSettingPageRangeFrom);
      base::Optional<int> to = value.FindIntKey(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.
      new_ranges.push_back(PageRange{from.value() - 1, to.value() - 1});
    }
  }
  settings->set_ranges(new_ranges);

  base::Optional<bool> collate = job_settings.FindBoolKey(kSettingCollate);
  base::Optional<int> copies = job_settings.FindIntKey(kSettingCopies);
  base::Optional<int> color = job_settings.FindIntKey(kSettingColor);
  base::Optional<int> duplex_mode = job_settings.FindIntKey(kSettingDuplexMode);
  base::Optional<bool> landscape = job_settings.FindBoolKey(kSettingLandscape);
  const std::string* device_name =
      job_settings.FindStringKey(kSettingDeviceName);
  base::Optional<int> scale_factor =
      job_settings.FindIntKey(kSettingScaleFactor);
  base::Optional<bool> rasterize_pdf =
      job_settings.FindBoolKey(kSettingRasterizePdf);
  base::Optional<int> pages_per_sheet =
      job_settings.FindIntKey(kSettingPagesPerSheet);

  if (!collate.has_value() || !copies.has_value() || !color.has_value() ||
      !duplex_mode.has_value() || !landscape.has_value() || !device_name ||
      !scale_factor.has_value() || !rasterize_pdf.has_value() ||
      !pages_per_sheet.has_value()) {
    return false;
  }
#if defined(OS_WIN)
  base::Optional<int> dpi_horizontal =
      job_settings.FindIntKey(kSettingDpiHorizontal);
  base::Optional<int> dpi_vertical =
      job_settings.FindIntKey(kSettingDpiVertical);
  if (!dpi_horizontal.has_value() || !dpi_vertical.has_value())
    return false;

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

  settings->set_collate(collate.value());
  settings->set_copies(copies.value());
  settings->SetOrientation(landscape.value());
  settings->set_device_name(base::UTF8ToUTF16(*device_name));
  settings->set_duplex_mode(static_cast<DuplexMode>(duplex_mode.value()));
  settings->set_color(static_cast<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());
  base::Optional<bool> is_modifiable =
      job_settings.FindBoolKey(kSettingPreviewModifiable);
  if (is_modifiable.has_value()) {
    settings->set_is_modifiable(is_modifiable.value());
#if defined(OS_WIN)
    settings->set_print_text_with_gdi(is_modifiable.value());
#endif
  }

#if defined(OS_CHROMEOS)
  bool send_user_info =
      job_settings.FindBoolKey(kSettingSendUserInfo).value_or(false);
  settings->set_send_user_info(send_user_info);
  if (send_user_info) {
    const std::string* username = job_settings.FindStringKey(kSettingUsername);
    if (username)
      settings->set_username(*username);
  }

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

  return true;
}

void PrintSettingsToJobSettingsDebug(const PrintSettings& settings,
                                     base::DictionaryValue* job_settings) {
  job_settings->SetBoolean(kSettingHeaderFooterEnabled,
                           settings.display_header_footer());
  job_settings->SetString(kSettingHeaderFooterTitle, settings.title());
  job_settings->SetString(kSettingHeaderFooterURL, settings.url());
  job_settings->SetBoolean(kSettingShouldPrintBackgrounds,
                           settings.should_print_backgrounds());
  job_settings->SetBoolean(kSettingShouldPrintSelectionOnly,
                           settings.selection_only());
  job_settings->SetInteger(kSettingMarginsType, settings.margin_type());
  if (!settings.ranges().empty()) {
    auto page_range_array = std::make_unique<base::ListValue>();
    for (size_t i = 0; i < settings.ranges().size(); ++i) {
      auto dict = std::make_unique<base::DictionaryValue>();
      dict->SetInteger(kSettingPageRangeFrom, settings.ranges()[i].from + 1);
      dict->SetInteger(kSettingPageRangeTo, settings.ranges()[i].to + 1);
      page_range_array->Append(std::move(dict));
    }
    job_settings->Set(kSettingPageRange, std::move(page_range_array));
  }

  job_settings->SetBoolean(kSettingCollate, settings.collate());
  job_settings->SetInteger(kSettingCopies, settings.copies());
  job_settings->SetInteger(kSettingColor, settings.color());
  job_settings->SetInteger(kSettingDuplexMode, settings.duplex_mode());
  job_settings->SetBoolean(kSettingLandscape, settings.landscape());
  job_settings->SetString(kSettingDeviceName, settings.device_name());
  job_settings->SetInteger(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.
  auto debug = std::make_unique<base::DictionaryValue>();
  debug->SetInteger("dpi", settings.dpi());
  debug->SetInteger("deviceUnitsPerInch", settings.device_units_per_inch());
  debug->SetBoolean("support_alpha_blend", settings.should_print_backgrounds());
  debug->SetString("media_vendor_id", settings.requested_media().vendor_id);
  SetSizeToJobSettings("media_size", settings.requested_media().size_microns,
                       debug.get());
  SetMarginsToJobSettings("requested_custom_margins_in_points",
                          settings.requested_custom_margins_in_points(),
                          debug.get());
  const PageSetup& page_setup = settings.page_setup_device_units();
  SetMarginsToJobSettings("effective_margins", page_setup.effective_margins(),
                          debug.get());
  SetSizeToJobSettings("physical_size", page_setup.physical_size(),
                       debug.get());
  SetRectToJobSettings("overlay_area", page_setup.overlay_area(), debug.get());
  SetRectToJobSettings("content_area", page_setup.content_area(), debug.get());
  SetRectToJobSettings("printable_area", page_setup.printable_area(),
                       debug.get());
  job_settings->Set("debug", std::move(debug));
}

}  // namespace printing
