// Copyright 2018 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 "components/printing/browser/printer_capabilities_mac.h"

#import <AppKit/AppKit.h>

#include "base/files/file_path.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
#include "base/threading/scoped_blocking_call.h"
#include "printing/units.h"

namespace printing {

namespace {

// On macOS, the custom paper size UI limits the value to 99999.
constexpr int kMacPaperDimensionLimit = 99999 * kPointsPerInch;

}  // namespace

PrinterSemanticCapsAndDefaults::Papers GetMacCustomPaperSizes() {
  base::FilePath local_library;
  bool success =
      base::mac::GetUserDirectory(NSLibraryDirectory, &local_library);
  DCHECK(success);

  base::FilePath plist = local_library.Append("Preferences")
                             .Append("com.apple.print.custompapers.plist");
  return internal::GetMacCustomPaperSizesFromFile(plist);
}

namespace internal {

PrinterSemanticCapsAndDefaults::Papers GetMacCustomPaperSizesFromFile(
    const base::FilePath& path) {
  PrinterSemanticCapsAndDefaults::Papers custom_paper_sizes;

  base::scoped_nsobject<NSDictionary> custom_papers_dict;
  {
    base::ScopedBlockingCall scoped_block(base::BlockingType::MAY_BLOCK);
    custom_papers_dict.reset([[NSDictionary alloc]
        initWithContentsOfFile:base::mac::FilePathToNSString(path)]);
  }

  for (id key in custom_papers_dict.get()) {
    NSDictionary* paper = [custom_papers_dict objectForKey:key];
    if (![paper isKindOfClass:[NSDictionary class]])
      continue;

    int width = [[paper objectForKey:@"width"] intValue];
    int height = [[paper objectForKey:@"height"] intValue];
    if (width <= 0 || height <= 0 || width > kMacPaperDimensionLimit ||
        height > kMacPaperDimensionLimit) {
      continue;
    }

    NSString* name = [paper objectForKey:@"name"];
    if (![name isKindOfClass:[NSString class]] || [name length] == 0)
      continue;

    gfx::Size size_microns(
        ConvertUnit(width, kPointsPerInch, kMicronsPerInch),
        ConvertUnit(height, kPointsPerInch, kMicronsPerInch));
    custom_paper_sizes.push_back(
        {base::SysNSStringToUTF8(name), "", size_microns});
  }

  return custom_paper_sizes;
}

}  // namespace internal

}  // namespace printing
