/**
 * Copyright (C) 2003-2026, Foxit Software Inc..
 * All Rights Reserved.
 *
 * http://www.foxitsoftware.com
 *
 * The following code is copyrighted and is the proprietary of Foxit Software Inc.. It is not allowed to
 * distribute any parts of Foxit PDF Conversion SDK to third party or public without permission unless an agreement
 * is signed between Foxit Software Inc. and customers to explicitly grant customers permissions.
 *
 * @file fs_common.h
 * @brief Header file for common definitions and classes.
 */

#ifndef FS_COMMON_H_
#define FS_COMMON_H_

#include "fs_basictypes.h"

/**
 * @brief Foxit namespace.
 *
 * @details All the definitions and classes of Foxit PDF Conversion SDK are defined within this namespace.
 */
namespace foxit {
/**
 * @brief Common namespace.
 */
namespace common {
  /**
   * @brief Enumeration for user access permissions in a PDF document.
   *
   * @details Values of this enumeration can be used alone or in combination.
   */
  typedef enum _UserPermissions {
    /**
     * @brief Print PDF document with normal mode. (Bit 3 in permission value)
     * @details If user wants to print a higher quality level of PDF document, please set current value with
     *         value @link PDFDoc::e_PermPrintHigh @endlink together.
     */
    e_PermPrint = 0x0004,
      /**
       * @brief Modify PDF contents. (Bit 4 in permission value)
       * @details If this value is set, user can modify contents of PDF document by operations other than those controlled by
       *         values @link PDFDoc::e_PermAnnotForm @endlink, @link PDFDoc::e_PermFillForm @endlink and
       *         @link PDFDoc::e_PermAssemble @endlink.
       */
    e_PermModify = 0x0008,
      /**
       * @brief Extract PDF contents. (Bit 5 in permission value)
       * @details If this value is set, user can copy or otherwise extract text and graphics from the document
       *         by operations other than that controlled by value @link PDFDoc::e_PermExtractAccess @endlink.
       */
    e_PermExtract = 0x0010,
      /**
       * @brief Operate text annotations and fill in interactive form fields. (Bit 6 in permission value)
       * @details If value @link PDFDoc::e_PermModify @endlink is also set,
       *          user can create or modify interactive form fields (including signature fields).
       */
    e_PermAnnotForm = 0x0020,
      /**
       * @brief Fill PDF form. (Bit 9 in permission value)
       * @details If this value is set, user can fill in interactive form fields (including signature fields),
       *         even if value @link PDFDoc::e_PermAnnotForm @endlink is not used.
       */
    e_PermFillForm = 0x0100,
      /**
       * @brief Disabilities support. (Bit 10 in permission value)
       * @details If this value is set, user can extract text and graphics in support of accessibility
       *         to users with disabilities or for other purposes.
       */
    e_PermExtractAccess = 0x0200,
      /**
       * @brief Assemble PDF document. (Bit 11 in permission value)
       * @details If this value is set, it enables to assemble the document
       *         (Insert, rotate, or delete pages and create bookmarks or thumbnail images),
       *         regardless if value @link PDFDoc::e_PermModify @endlink is set or not.
       */
    e_PermAssemble = 0x0400,
      /**
       * @brief Print PDF document with higher qualities. (Bit 12 in permission value)
       * @details If this value is not set (and value @link PDFDoc::e_PermPrint @endlink is set),
       *         printing is limited to a low-level representation of the appearance, possibly of degraded quality.
       */
    e_PermPrintHigh = 0x0800
  } UserPermissions;
  

/**
 * This class represents a callback object used to check the convert condition for the PDF to Office conversion.
 * All the pure virtual functions in this class are used as callback functions and should be implemented by user.
 * This is called when the required permissions for converting the PDF documents are not met.
 */
class ConvertCheckCallback {
 public:
  /**
   * @brief Check user permissions to decide whether to proceed with the PDF to Office conversion.
   *
   * @param user_permissions The user permissions. Please refer to values starting from
   *                         @link common::e_PermPrint @endlink and this should be one or combination of these values.
   *
   * @return <b>true</b> means the PDF to Office conversion will continue,
   *         while <b>false</b> the PDF to Office conversion will not continue.
   */
  virtual bool CheckUserPermissions(uint32 user_permissions) = 0;
};

/**
 * This class represents the library management.
 * It contains functions to initialize/re-initialize/release Foxit PDF Conversion SDK library, and also contains functions
 * for global use.<br>
 * Any application should load Foxit PDF Conversion SDK by function @link Library::Initialize @endlink before calling any other
 * Foxit PDF Conversion SDK functions. When there is no need to use Foxit PDF Conversion SDK any more, please call
 * function @link Library::Release @endlink.<br>
 * Functions in Foxit PDF Conversion SDK may throw exception when some error occurs. User can catch these exceptions and
 * check the error code with values starting from @link foxit::e_ErrFile @endlink to know more about what error occurs.
 * 
 * @note During the life-cycle of an application, @link Library::Initialize @endlink and @link Library::Release @endlink should
 *       be called in pair and can only be called once. Once @link Library::Release @endlink is called during
 *       the life-cycle of an application, Foxit PDF Conversion SDK cannot be initialized any more in the life-cycle of the application.
 *       Before @link Library::Release @endlink is called, if user wants to re-initialize Foxit PDF Conversion SDK, please refer to
 *       function @link Library::Reinitialize @endlink.
 */
class Library FS_FINAL : public Object {
 public:
  /**
   * @brief Initialize Foxit PDF Conversion SDK Library, with valid license information.
   *
   * @details During the life-cycle of an application, this function can only be called once and
   *          should be called first before any other functions in Foxit PDF Conversion SDK can be called.<br>
   *          Once function @link Library::Release @endlink is called, Foxit PDF Conversion SDK library cannot
   *          be initialized any more in the life-cycle of the application.
   *
   * @param[in] sn   String of sn information, which can be retrieved from "SN=" part in key file "gsdk_sn.txt" or "rdk_sn.txt".
   * @param[in] key  String of key information, which can be retrieved from "Sign=" part in key file "gsdk_key.txt" or "rdk_key.txt".
   *
   * @return @link foxit::e_ErrSuccess @endlink means success.<br>
   *         @link foxit::e_ErrInvalidLicense @endlink means input license information is invalid.<br>
   *         @link foxit::e_ErrParam @endlink means parameter <i>sn</i> or <i>key</i> is an empty string.<br>
   *         For more information about error code values, please refer to values starting from @link foxit::e_ErrSuccess @endlink.
   */
  static ErrorCode Initialize(const char* sn, const char* key);

  /**
   * @brief Re-initialize Foxit PDF Conversion SDK Library.
   *
   * @details When user meets out-of-memory error or user wants to re-initialize Foxit PDF Conversion SDK library before
   *          function @link Library::Release @endlink is called, user can call this function to re-initialize Foxit PDF Conversion SDK Library.<br>
   *          Once function @link Library::Release @endlink is called, Foxit PDF Conversion SDK library cannot
   *          be initialized any more in the life-cycle of the application.
   *
   * @return @link foxit::e_ErrSuccess @endlink means success.
   *         For more information about error code values, please refer to values starting from @link foxit::e_ErrSuccess @endlink.
   */
  static ErrorCode Reinitialize();

  /**
   * @brief Release all resource allocated by Foxit PDF Conversion SDK Library.
   *
   * @details User should call this function to release all memory blocks allocated by the library.<br>
   *          Once this fucntion is called, Foxit PDF Conversion SDK library cannot be initialized any more
   *          in the life-cycle of the application.
   *
   * @return None.
   */
  static void Release();

  /**
   * @brief Get the version of current Foxit PDF Conversion SDK library.
   *
   * @return Version string.
   */
  static String GetVersion();

  /**
   * @brief Enable thread safety.
   *
   * @param[in] is_enable_thread_safety  Enable thread safety.<b>true</b> means to enable thread safety,
   *                                     while <b>false</b> means to disable thread safety.
   *
   * @return None.
   */
  static void EnableThreadSafety(bool is_enable_thread_safety);

  /**
   * @brief Set the callback object to check the PDF to Office conversion conditions.
   *
   * @details This method allows you to specify a custom convert check callback that will be called 
   *        to evaluate whether the conversion from PDF to Office should proceed, based on user-defined logic 
   *        , when the required permissions for converting the PDF documents are not met.
   *
   * @param[in] convert_check_callback A customized convert check callback which is implemented based on callback 
   *                                   class @link common::ConvertCheckCallback @endlink. If this is <b>NULL</b>, customized convert 
   *                                   check callback will be removed and default convert check will be used instead.
   *  
   * @return <b>true</b> means success, while <b>false</b> means failure.
   */
  static bool SetConvertCheckCallback(ConvertCheckCallback* convert_check_callback);

 private:
  Library(const Library&);
  Library& operator = (const Library&);
};

/**
 * This class represents a progressive object, which is used for progressive process as converting PDF document to Office document.
 */
class Progressive : public Base {
 public:
  /**
   * @brief Enumeration for progress state.
   *
   * @details Values of this enumeration should be used alone.
   */
  typedef enum _State {
    /** @brief Progress state: any error occurs. */
    e_Error = 0,
    /** @brief Progress state: progress needs to be continued. */
    e_ToBeContinued = 1,
    /** @brief Progress state: progress is finished. */
    e_Finished = 2
  } State;
  
  /**
   * @brief Constructor, with another progressive object.
   *
   * @param[in] other  Another progressive object.
   */
  Progressive(const Progressive& other);
  /** @brief Destructor. */
  ~Progressive();

  /**
   * @brief Assign operator.
   *
   * @param[in] other  Another progressive object, whose value would be assigned to current object.
   *
   * @return Reference to current object itself.
   */
  Progressive& operator = (const Progressive& other);

  /**
   * @brief Continue the progressive process.
   *
   * @return @link Progressive::e_Finished @endlink means current process is finished successfully.<br>
   *         @link Progressive::e_ToBeContinued @endlink means current process is suspended,
   *         and this function needs to be called again to continue the process.<br>
   *         @link Progressive::e_Error @endlink means any error occurs.
   */
  State Continue();

  /**
   * @brief Get the rate of current progress.
   *
   * @return An integer between 0 and 100 (inclusive), indicating the rate of current progress.
   *         -1 means error.
   */
  int GetRateOfProgress();

  // User is strongly recommended NOT to use this method; otherwise unknown situation may occur.
  explicit Progressive(FS_HANDLE handle = NULL);
};

/**
 * This class represents index range. Here, a range consists of one or more segments and each segment consists of
 * one single index or a group of consecutive indexes.<br>
 * For some special case, such as used in @link conversion::pdf2office::PDF2OfficeSettingData @endlink, index values specified in this range represent page numbers directly instead of page indexes.
 *
 * @see @link conversion::pdf2office::PDF2OfficeSettingData @endlink
 */
class Range FS_FINAL : public Base{
 public:
  /**
   * @brief Enumeration for range filter.
   *
   * @details Values of this enumeration should be used alone.
   */
  typedef enum _Filter {
    /** @brief All the indexes within a range will be used. */
    e_All = 0,
    /** @brief Only even numbers in a range will be used (discards odd numbers). */
    e_Even = 1,
    /** @brief Only odd numbers in a range will be used (discards even numbers). */
    e_Odd = 2
  } Filter;
  
    /** @brief Constructor. */
    Range();

  /**
   * @brief Constructor, with a single index.
   *
   * @param[in] index  A single index.
   */
  explicit Range(int index);

  /**
   * @brief Constructor, with a specified index range.
   *
   * @param[in] start_index  The start index of a range segment.
   * @param[in] end_index    The end index of a range segment.
   * @param[in] filter       Filter type to decide which indexes of this range would be used. Please refer to values
   *                         starting from @link Range::e_All @endlink and this should be one of these values.
   *                         Default value: @link Range::e_All @endlink.<br>
   *                         Specially, when this value is @link Range::e_Even @endlink or @link Range::e_Odd @endlink,
   *                         that means each even or odd number within the specified range segment will
   *                         be treated as a single segment.
   */
  explicit Range(int start_index, int end_index, Filter filter = e_All);

  /**
   * @brief Constructor, with another range object.
   *
   * @param[in] other  Another range object.
   */
  Range(const Range& other);

  /** @brief Destructor. */
  ~Range();

  /**
   * @brief Assign operator.
   *
   * @param[in] other  Another range object, whose value would be assigned to current object.
   *
   * @return Reference to current object itself.
   */
  Range& operator = (const Range& other);

  /**
   * @brief Equal operator.
   *
   * @param[in] other  Another range object. This function will check if current object is equal to this one.
   *
   * @return <b>true</b> means equal, while <b>false</b> means not equal.
   */
  bool operator == (const Range& other) const;

  /**
   * @brief Not equal operator.
   *
   * @param[in] other  Another range object. This function will check if current object is not equal to this one.
   *
   * @return <b>true</b> means not equal, while <b>false</b> means equal.
   */
  bool operator != (const Range& other) const;

  /**
   * @brief Check whether current object is empty or not.
   *
   * @details When the current object is empty, that means current object is useless.
   *
   * @return <b>true</b> means current object is empty, while <b>false</b> means not.
   */
  bool IsEmpty() const;

  /**
   * @brief Add an index as a new range segment.
   *
   * @param[in] index  An index to be added as a new range segment.
   */
  void AddSingle(int index);

  /**
   * @brief Add a new range segment. (Reverse ordering is legal.)
   *
   * @param[in] start_index  The start index of a new range segment.
   * @param[in] end_index    The end index of a new range segment.
   * @param[in] filter       Filter type to decide which indexes of this range would be used. Please refer to values
   *                         starting from @link Range::e_All @endlink and this should be one of these values.
   *                         Default value: @link Range::e_All @endlink.<br>
   *                         Specially, when this value is @link Range::e_Even @endlink or @link Range::e_Odd @endlink,
   *                         that means each even or odd number within the specified range segment will
   *                         be treated as a single segment.
   *
   * @return None.
   */
  void AddSegment(int start_index, int end_index, Filter filter = e_All);

  /**
   * @brief Get the count of range segments.
   *
   * @return The count of range segments.
   */
  int GetSegmentCount() const;

  /**
   * @brief Get the start index of a specified range segment.
   *
   * @param[in] segment_index  The segment index. Valid range: 0 to (<i>count</i>-1).
   *                           <i>count</i> is returned by function @link Range::GetSegmentCount @endlink.
   *
   * @return The start index of a specified range segment.
   */
  int GetSegmentStart(int segment_index) const;

  /**
   * @brief Get the end index of a specified range segment.
   *
   * @param[in] segment_index  The segment index. Valid range: 0 to (<i>count</i>-1).
   *                           <i>count</i> is returned by function @link Range::GetSegmentCount @endlink.
   *
   * @return The end index of a specified range segment.
   */
  int GetSegmentEnd(int segment_index) const;

  /**
   * @brief Remove all range segments.
   *
   * @return None.
   */
  void RemoveAll();

  // User is strongly recommended NOT to use this method; otherwise unknown situation may occur.
  explicit Range(FS_HANDLE handle);
};

}  // namespace common
}  // namespace foxit

#endif  // FS_COMMON_H_

