/* Copyright (C) 2006 The gtkmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <https://www.gnu.org/licenses/>.
 */

#include <vector>

#include <glibmm/object.h>
#include <gtkmm/enums.h>
#include <gtkmm/papersize.h>

_DEFS(gtkmm,gtk)
_PINCLUDE(glibmm/private/object_p.h)

namespace Gtk
{

_WRAP_ENUM(PrintDuplex, GtkPrintDuplex, decl_prefix GTKMM_API)
_WRAP_ENUM(PrintQuality, GtkPrintQuality, decl_prefix GTKMM_API)
_WRAP_ENUM(PrintPages, GtkPrintPages, decl_prefix GTKMM_API)
_WRAP_ENUM(PageSet, GtkPageSet, decl_prefix GTKMM_API)
_WRAP_ENUM(NumberUpLayout, GtkNumberUpLayout, decl_prefix GTKMM_API)

/** A page range.
 */
class GTKMM_API PageRange
{
public:
  PageRange();
  PageRange(int start, int end);

  int start;
  int end;
};

#ifndef DOXYGEN_SHOULD_SKIP_THIS
struct PageRangeTraits
{
  using CppType       = PageRange;
  using CType         = GtkPageRange;
  using CTypeNonConst = GtkPageRange;

  static CType   to_c_type      (CType c_obj)            { return c_obj; }
  static void    release_c_type (CType)                  {}
  static CType   to_c_type      (const CppType& cpp_obj) { CTypeNonConst c_obj = {cpp_obj.start, cpp_obj.end}; return c_obj; }
  static CppType to_cpp_type    (CType c_obj)            { return CppType (c_obj.start, c_obj.end); }
};
#endif // DOXYGEN_SHOULD_SKIP_THIS

/** A PrintSettings object represents the settings of a print dialog in a system-independent way.
 * The main use for this object is that once you've printed you can get a settings object that
 * represents the settings the user chose, and the next time you print you can pass that object
 * in so that the user doesn't have to re-set all his settings.
 *
 * It's also possible to enumerate the settings so that you can easily save the settings for the
 * next time your app runs, or even store them in a document. The predefined keys try to use shared
 * values as much as possible so that moving such a document between systems still works.
 *
 * @ingroup Printing
 */
class GTKMM_API PrintSettings : public Glib::Object
{
  _CLASS_GOBJECT(PrintSettings, GtkPrintSettings, GTK_PRINT_SETTINGS, Glib::Object, GObject, , , GTKMM_API)
protected:
  _CTOR_DEFAULT

public:
  _WRAP_CREATE()

 /** Reads the print settings from the @a key_file.
  * Returns a new %PrintSettings object with the restored settings,
  * or an empty RefPtr if an error occurred.
  * See save_to_key_file().
  *
  * @param key_file The KeyFile to retrieve the settings from.
  * @result The restored PrintSettings
  *
  * @throws Glib::KeyFileError, Glib::FileError
  */
  static Glib::RefPtr<PrintSettings> create_from_key_file(const Glib::RefPtr<const Glib::KeyFile>& key_file);

 /** Reads the print settings from the group @a group_name in @a key_file.
  * Returns a new %PrintSettings object with the restored settings,
  * or an empty RefPtr if an error occurred.
  * See save_to_key_file().
  *
  * @param key_file The KeyFile to retrieve the settings from.
  * @param group_name The name of the group to use.
  * @result The restored %PrintSettings
  *
  * @throws Glib::KeyFileError, Glib::FileError
  */
  static Glib::RefPtr<PrintSettings> create_from_key_file(const Glib::RefPtr<const Glib::KeyFile>& key_file, const Glib::ustring& group_name);
  _IGNORE(gtk_print_settings_new_from_key_file)

 /** Reads the print settings from @a file_name. Returns a new %PrintSettings
  * object with the restored settings, or an empty RefPtr if an error occurred.
  * See save_to_file().
  *
  * @param file_name The filename to read the settings from.
  * @result the restored %PrintSettings
  *
  * @throws Glib::KeyFileError, Glib::FileError
  */
  static Glib::RefPtr<PrintSettings> create_from_file(const std::string& file_name);
  _IGNORE(gtk_print_settings_new_from_file)

  /** Print settings keys.
   */
  class Keys
  {
  public:
    static const Glib::ustring PRINTER;
    static const Glib::ustring ORIENTATION;
    static const Glib::ustring PAPER_FORMAT;
    static const Glib::ustring PAPER_WIDTH;
    static const Glib::ustring PAPER_HEIGHT;
    static const Glib::ustring NUM_COPIES;
    static const Glib::ustring DEFAULT_SOURCE;
    static const Glib::ustring QUALITY;
    static const Glib::ustring RESOLUTION;
    static const Glib::ustring USE_COLOR;
    static const Glib::ustring DUPLEX;
    static const Glib::ustring COLLATE;
    static const Glib::ustring REVERSE;
    static const Glib::ustring MEDIA_TYPE;
    static const Glib::ustring DITHER;
    static const Glib::ustring SCALE;
    static const Glib::ustring PRINT_PAGES;
    static const Glib::ustring PAGE_RANGES;
    static const Glib::ustring PAGE_SET;
    static const Glib::ustring FINISHINGS;
    static const Glib::ustring NUMBER_UP;
    static const Glib::ustring NUMBER_UP_LAYOUT;
    static const Glib::ustring OUTPUT_BIN;

    static const Glib::ustring OUTPUT_FILE_FORMAT;
    static const Glib::ustring OUTPUT_URI;

    static const Glib::ustring WIN32_DRIVER_VERSION;
    static const Glib::ustring WIN32_DRIVER_EXTRA;
  };

  _WRAP_METHOD(Glib::RefPtr<PrintSettings> copy() const, gtk_print_settings_copy)

  //The from_ infix was added to these functions to make them clearer. GTK+ didn't want to change them.
  _WRAP_METHOD(bool load_from_file(const std::string& file_name),
    gtk_print_settings_load_file, errthrow "Glib::KeyFileError, Glib::FileError")

  _WRAP_METHOD(bool load_from_key_file(const Glib::RefPtr<const Glib::KeyFile>& key_file, const Glib::ustring& group_name),
    gtk_print_settings_load_key_file, errthrow "Glib::KeyFileError, Glib::FileError")

 /** Reads the print settings from the @a key_file.
  * See save_to_key_file().
  *
  * @param key_file The KeyFile to retrieve the settings from.
  * @result true on success.
  *
  * @throws Glib::KeyFileError, Glib::FileError
  */
  bool load_from_key_file(const Glib::RefPtr<const Glib::KeyFile>& key_file);

  //The save_ prefix was added to these functions to make them clearer. GTK+ didn't want to change them.
  _WRAP_METHOD(bool save_to_file(const std::string& file_name) const,
    gtk_print_settings_to_file, errthrow "Glib::KeyFileError, Glib::FileError")

  _WRAP_METHOD(void save_to_key_file(const Glib::RefPtr<Glib::KeyFile>& key_file, const Glib::ustring& group_name) const, gtk_print_settings_to_key_file)

  /** This function adds the print settings from @a settings to @a key_file,
   * in the "Print Settings" group.
   *
   * @param key_file The Glib::KeyFile to save the print settings to.
   */
  void save_to_key_file(const Glib::RefPtr<Glib::KeyFile>& key_file) const;

  _WRAP_METHOD(bool has_key(const Glib::ustring& key) const, gtk_print_settings_has_key)

  _WRAP_METHOD(Glib::ustring get(const Glib::ustring& key) const, gtk_print_settings_get)

  _WRAP_METHOD(void set(const Glib::ustring& key, const Glib::ustring& value), gtk_print_settings_set)
  _WRAP_METHOD(void unset(const Glib::ustring& key), gtk_print_settings_unset)

  /** For example,
   * void on_foreach_setting(const Glib::ustring& key, const Glib::ustring& value);
   */
  typedef sigc::slot<void(const Glib::ustring&, const Glib::ustring&)> SlotForeach;

  /** Calls a function for each print setting.
  * @param slot The callback to call for each print setting.
  */
  void setting_foreach(const SlotForeach& slot);

 _IGNORE(gtk_print_settings_foreach)

  _WRAP_METHOD(bool get_bool(const Glib::ustring& key) const, gtk_print_settings_get_bool)
  _WRAP_METHOD(void set_bool(const Glib::ustring& key, bool value = true), gtk_print_settings_set_bool)

  _WRAP_METHOD(double get_double(const Glib::ustring& key) const, gtk_print_settings_get_double)
  _WRAP_METHOD(double get_double_with_default(const Glib::ustring& key, double def) const,
               gtk_print_settings_get_double_with_default)
  _WRAP_METHOD(void set_double(const Glib::ustring& key, double value), gtk_print_settings_set_double)

  _WRAP_METHOD(double get_length(const Glib::ustring& key, Unit unit) const, gtk_print_settings_get_length)
  _WRAP_METHOD(void set_length(const Glib::ustring& key, double value, Unit unit), gtk_print_settings_set_length)

  _WRAP_METHOD(int get_int(const Glib::ustring& key) const, gtk_print_settings_get_int)
  _WRAP_METHOD(int get_int_with_default(const Glib::ustring& key, int def) const,
               gtk_print_settings_get_int_with_default)
  _WRAP_METHOD(void set_int(const Glib::ustring& key, int value), gtk_print_settings_set_int)

  // helpers:

  _WRAP_METHOD(Glib::ustring get_printer() const, gtk_print_settings_get_printer)
  _WRAP_METHOD(void set_printer(const Glib::ustring& printer), gtk_print_settings_set_printer)

  _WRAP_METHOD(PageOrientation get_orientation() const, gtk_print_settings_get_orientation)
  _WRAP_METHOD(void set_orientation(PageOrientation orientation), gtk_print_settings_set_orientation)

  _WRAP_METHOD(PaperSize get_paper_size(), gtk_print_settings_get_paper_size)
  _WRAP_METHOD(const PaperSize get_paper_size() const, gtk_print_settings_get_paper_size, constversion)
  _WRAP_METHOD(void set_paper_size(const PaperSize& paper_size), gtk_print_settings_set_paper_size)

  _WRAP_METHOD(double get_paper_width(Unit unit) const, gtk_print_settings_get_paper_width)
  _WRAP_METHOD(void set_paper_width(double width, Unit unit), gtk_print_settings_set_paper_width)
  _WRAP_METHOD(double get_paper_height(Unit unit) const, gtk_print_settings_get_paper_height)
  _WRAP_METHOD(void set_paper_height(double height, Unit unit), gtk_print_settings_set_paper_height)

  _WRAP_METHOD(bool get_use_color() const, gtk_print_settings_get_use_color)
  _WRAP_METHOD(void set_use_color(bool use_color = true), gtk_print_settings_set_use_color)

  _WRAP_METHOD(bool get_collate() const, gtk_print_settings_get_collate)
  _WRAP_METHOD(void set_collate(bool collate = true), gtk_print_settings_set_collate)

  _WRAP_METHOD(bool get_reverse() const, gtk_print_settings_get_reverse)
  _WRAP_METHOD(void set_reverse(bool reverse = true), gtk_print_settings_set_reverse)

  _WRAP_METHOD(PrintDuplex get_duplex() const, gtk_print_settings_get_duplex)
  _WRAP_METHOD(void set_duplex(PrintDuplex duplex), gtk_print_settings_set_duplex)

  _WRAP_METHOD(PrintQuality get_quality() const, gtk_print_settings_get_quality)
  _WRAP_METHOD(void set_quality(PrintQuality quality), gtk_print_settings_set_quality)

  _WRAP_METHOD(int get_n_copies() const, gtk_print_settings_get_n_copies)
  _WRAP_METHOD(void set_n_copies(int num_copies), gtk_print_settings_set_n_copies)

  _WRAP_METHOD(int get_number_up() const, gtk_print_settings_get_number_up)
  _WRAP_METHOD(void set_number_up(int number_up), gtk_print_settings_set_number_up)

  _WRAP_METHOD(NumberUpLayout get_number_up_layout() const, gtk_print_settings_get_number_up_layout)
  _WRAP_METHOD(void set_number_up(NumberUpLayout number_up_layout), gtk_print_settings_set_number_up_layout)

  _WRAP_METHOD(int get_resolution() const, gtk_print_settings_get_resolution)
  _WRAP_METHOD(void set_resolution(int resolution), gtk_print_settings_set_resolution)

  _WRAP_METHOD(int get_resolution_x() const, gtk_print_settings_get_resolution_x)
  _WRAP_METHOD(int get_resolution_y() const, gtk_print_settings_get_resolution_y)
  _WRAP_METHOD(void set_resolution_xy(int resolution_x, int resolution_y), gtk_print_settings_set_resolution_xy)
  _WRAP_METHOD(double get_printer_lpi() const, gtk_print_settings_get_printer_lpi)
  _WRAP_METHOD(void set_printer_lpi(double lpi), gtk_print_settings_set_printer_lpi)

  _WRAP_METHOD(double get_scale() const, gtk_print_settings_get_scale)
  _WRAP_METHOD(void set_scale(double scale), gtk_print_settings_set_scale)

  _WRAP_METHOD(PrintPages get_print_pages() const, gtk_print_settings_get_print_pages)
  _WRAP_METHOD(void set_print_pages(PrintPages pages), gtk_print_settings_set_print_pages)

  std::vector<PageRange> get_page_ranges() const;
  void set_page_ranges(const std::vector<PageRange>& page_ranges);

  _IGNORE(gtk_print_settings_get_page_ranges, gtk_print_settings_set_page_ranges)

  _WRAP_METHOD(PageSet get_page_set() const, gtk_print_settings_get_page_set)
  _WRAP_METHOD(void set_page_set(PageSet page_set), gtk_print_settings_set_page_set)

  _WRAP_METHOD(Glib::ustring get_default_source() const, gtk_print_settings_get_default_source)
  _WRAP_METHOD(void set_default_source(const Glib::ustring& default_source), gtk_print_settings_set_default_source)

  _WRAP_METHOD(Glib::ustring get_media_type() const, gtk_print_settings_get_media_type)
  _WRAP_METHOD(void set_media_type(const Glib::ustring& media_type), gtk_print_settings_set_media_type)

  _WRAP_METHOD(Glib::ustring get_dither() const, gtk_print_settings_get_dither)
  _WRAP_METHOD(void set_dither(const Glib::ustring& dither), gtk_print_settings_set_dither)

  _WRAP_METHOD(Glib::ustring get_finishings() const, gtk_print_settings_get_finishings)
  _WRAP_METHOD(void set_finishings(const Glib::ustring& finishings), gtk_print_settings_set_finishings)

  _WRAP_METHOD(Glib::ustring get_output_bin() const, gtk_print_settings_get_output_bin)
  _WRAP_METHOD(void set_output_bin(const Glib::ustring& output_bin), gtk_print_settings_set_output_bin)

  //There are no properties.
};

} // namespace Gtk
