// 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 {

void GetCustomMarginsFromJobSettings(const base::Value& settings,
                                     PageMargins* page_size_margins) {
  const base::Value* custom_margins = settings.FindKey(kSettingMarginsCustom);
  if (!custom_margins) {
    NOTREACHED();
    return;
  }
  page_size_margins->top =
      custom_margins->FindKey(kSettingMarginTop)->GetDouble();
  page_size_margins->bottom =
      custom_margins->FindKey(kSettingMarginBottom)->GetDouble();
  page_size_margins->left =
      custom_margins->FindKey(kSettingMarginLeft)->GetDouble();
  page_size_margins->right =
      custom_margins->FindKey(kSettingMarginRight)->GetDouble();
}

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) {
    PageMargins margins_in_points;
    margins_in_points.Clear();
    GetCustomMarginsFromJobSettings(job_settings, &margins_in_points);
    settings->SetCustomMargins(margins_in_points);
  }

  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);
  }
#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
