// Copyright (C) 2003-2026, Foxit Software Inc..
// All Rights Reserved.
//
// http://www.foxitsoftware.com
//
// The following code is copyrighted and contains proprietary information and trade secrets of Foxit Software Inc..
// You cannot distribute any part of Foxit PDF SDK to any third party or general public,
// unless there is a separate license agreement with Foxit Software Inc. which explicitly grants you such rights.
//
// This file contains an example to demonstrate how to use Foxit PDF SDK to operate PDF objects directly.

#include "FSPDFObjC.h"

NSString *input_path = @"../input_files/";
NSString *output_path = @"../output_files/";

NSString *sn = @"bPxThFlBAYifO3yiW0C51bKbjPap1zHaf5aG5sX378TjFvB7Q0802A==";
NSString *key = @"8f3g1sGNtR8NAgfSNv+BvaJWy2fnrw36NZvzh8GUxYXvs+/YczAk4e34yqlOnmL4asgxGMO7+rlOcSHUSSKagx5g4G7VEXfkYLXnDDx77FOOedZPrFFcOCu1vT4+wOKzy1zkORq9cKtiFf44byH5sfRqf+OvELjep2teT9eF9yPCsSw2vRKljXlPy40DMP9XX1O5OTe+mSG3RvwKUMb0+RpG3YobM87j+/ynTDlJMMXw4vgwuTb1ZuAtlvkTdFz7HDLV81C6TYnn73ddHeGD3qYWBVsD4uJkDwyyH/SWr7QX0HSgVg8HSZqnab1VGdAUYxKY2vGWeOTJdu6qDGb5ZEb9O3kZZg+9LYAmUKzDfCYwfIsYZ8Y9LPC4wMx70kIq7JpNnzPvigrdshV8/ew1F0+qP/P5Z1EB53vDVrp2LVSuL873Wv4g3PzjZlNH+1qgT87hC+Buto4qsSUfP5Y2z0uApu+c/TfttCXbeMLSsw9TY1HQD3mkrZExMaQqRrAuXAcZWdvBnVuG3DCZmm8q0DLxJiCfYfViAU/AkbeKMIGaTJdrvIXBcssfde4nmU6qr0M4x4+Hs2ESddtY2QRtLAUBq/7h7GJlJHkEZr8ueaUy/6D/2vvAWz6wMLgmjlPbDTLqzfnCJylHCPtcJmu1SPPT9v1VreBX3+zNWcIT8HueyHEiUniqzwWkRKaotrnNb/zhnHLPpgaBSwKjyi8rOzzVwu/nY84G9ye4jsVjmkIRItKDrW7z22iS+QQuTwfqLVuMB0OD4jMkPCC2slzPfEeZnuh4+Rewln2qLRJVgI72zJ20OBWAelGSpO1Ii2Y3gOvojdmtUwx6R3Z1qFNWTTB25o9ytcux8BLOtTCkA8T8xaT4N339OTCsu/TmfahIDixKvr8cDa6F2WkBT8SOfv64W9PgiNv5B/BMOD2VWYaAl0N7yD0NkYYg/cDWRC4dfpdeip1jrr0k3mND0oSpIkxC+FicZbaYYwRdtJ9OSVWJ5OE0voLv8HgLze8mw6s4TrN3z+a2NQCveMa2VRN7YcEF7agPrvb/qU+otMwHae/wM7+f+HFAaOW+WTfzfxIVFB8/A1DN0NiEX+em4G7nO5F5ZcvfYPpaaioe8Nn33BbVLtMjXqsOBeM8AXiVfpD6YO75j7BqnBUPnivvD8BxJaaIQZvVSuQmvGm0ynt03IYwE8Rq+jYsunvsZ86jh5BiUR+Nm7sK0Qe9BdZn/7jdqohMv9czfMGUAscX+xBMunFbDpcRbWVpUADcm209L8Ndek2XY7YlCMxPgPVNvfWRF2jxehib9Tpd7zB5ZIDfAEH9zrpLfp29DLvCh2Yx8mH7xxdKG1O9Q0GdHphYHhej6smAcPm68R0GUQaTOLfXqNpueGJC1GAOI3Y4swjyt7jMTWcibnKLzwukWE5rnEDhn5n64JnyUM0ZFkRmtOiV";

// This function is to do some operation to PDF object.
void ObjectOperation(FSPDFDoc *document) {
    FSPDFObject *boolean_object = [FSPDFObject createFromBoolean:YES];
    unsigned int boolean_object_number = [document addIndirectObject:boolean_object];
    NSLog(@"Object number of new boolean object: %d \r\n", boolean_object_number);
    bool boolean_object_value = [boolean_object getBoolean];
    NSLog(@"\tValue of new boolean object: %@\r\n", boolean_object_value ? @"true" : @"false");

    FSPDFObject *float_object = [FSPDFObject createFromFloat:0.1f];
    unsigned int float_object_number = [document addIndirectObject:float_object];
    NSLog(@"Object number of new number object (as float): %d \r\n", float_object_number);
    float float_object_value = [float_object getFloat];
    NSLog(@"\tValue of new number object (as float): %f \r\n", float_object_value);

    FSPDFObject *integer_object = [FSPDFObject createFromInteger:1];
    unsigned int integer_object_number = [document addIndirectObject:integer_object];
    NSLog(@"Object number of new number object (as integer): %d \r\n", integer_object_number);
    int integer_object_value = [integer_object getInteger];
    NSLog(@"\tValue of new number object (as Integer): %d \r\n", integer_object_value);

    FSPDFObject *string_object = [FSPDFObject createFromString:@"foxit"];
    unsigned int string_object_number = [document addIndirectObject:string_object];
    NSLog(@"Object number of new string object: %d \r\n", string_object_number);
    NSString *string_object_value = [string_object getWideString];
    NSLog(@"\tValue of new string object: %@ \r\n", string_object_value);

    FSPDFObject *name_object = [FSPDFObject createFromName:@"sdk"];
    unsigned int name_object_number = [document addIndirectObject:name_object];
    NSLog(@"Object number of new name object: %d \r\n", name_object_number);
    NSString *name_object_value = [name_object getName];
    NSLog(@"\tValue of new name object: %@ \r\n", name_object_value);

    FSDateTime *date_time = [[FSDateTime alloc] initWithYear:2017 month:9 day:27 hour:19 minute:36 second:6 milliseconds:0 utc_hour_offset:8 utc_minute_offset:0];
    FSPDFObject *datetime_object = [FSPDFObject createFromDateTime:date_time];
    unsigned int datetime_object_number = [document addIndirectObject:datetime_object];
    NSLog(@"Object number of new string object (as date-time): %d \r\n", datetime_object_number);
    NSString *datetime_object_value = [datetime_object getWideString];
    NSLog(@"\tValue of new string object (as date-time): %@ \r\n", datetime_object_value);

    FSPDFArray *array = [FSPDFArray create];
    FSPDFObject *boolean_object_reference = [FSPDFObject createReference:document object_number:boolean_object_number];
    unsigned int boolean_object_reference_number = [boolean_object_reference getObjNum];
    NSLog(@"Object number of a new reference object to a boolean object: %d \r\n", boolean_object_reference_number);
    FSPDFObject *float_object_reference = [FSPDFObject createReference:document object_number:float_object_number];
    FSPDFObject *integer_object_reference = [FSPDFObject createReference:document object_number:integer_object_number];
    FSPDFObject *integer_object_direct = [integer_object_reference getDirectObject];
    NSLog(@"Object number of the direct number object: %d \r\n", [integer_object_direct getObjNum]);
    FSPDFObject *string_object_reference = [FSPDFObject createReference:document object_number:string_object_number];
    FSPDFObject *name_object_reference = [FSPDFObject createReference:document object_number:string_object_number];
    FSPDFObject *datetime_object_reference = [FSPDFObject createReference:document object_number:string_object_number];

    [array addElement:boolean_object_reference];
    [array addElement:float_object_reference];
    [array addElement:integer_object_reference];
    [array addElement:string_object_reference];
    [array addElement:name_object_reference];
    [array addElement:datetime_object_reference];
    [array addElement:[boolean_object cloneObject]];

    unsigned int array_object_number = [document addIndirectObject:array];
    NSLog(@"Object number of array object: %d \r\n", array_object_number);
}

// This function is to remove some properties from catalog dictionary.
void RemoveCatalogKey(FSPDFDoc *document) {
    if ([document isEmpty]) {
        return;
    }
    FSPDFDictionary *catalog = [document getCatalog];
    if (catalog == NULL)
        return;

    NSArray *key_strings = [[NSArray alloc] initWithObjects:@"Type", @"Boolean", @"Name", @"String", @"Array", @"Dict", nil];
    for (int i = 0; i < [key_strings count]; i++) {
        if ([catalog hasKey:key_strings[i]]) {
            [catalog removeAt:key_strings[i]];
        }
    }
}

int main(int argc, const char *argv[]) {
    @autoreleasepool {
        NSString *output_directory = [output_path stringByAppendingString:@"pdfobjects/"];
        NSString *input_file = [input_path stringByAppendingString:@"pdfobjects.pdf"];
        NSFileManager *fileManager = [NSFileManager defaultManager];
        BOOL isDir = NO;
        if ([fileManager fileExistsAtPath:output_directory isDirectory:&isDir]) {
            if (!isDir) {
                NSError *error = nil;
                if (![fileManager removeItemAtPath:output_directory error:&error] || error) {
                    return -1;
                }
                if (![fileManager createDirectoryAtPath:output_directory withIntermediateDirectories:YES attributes:nil error:&error] || error) {
                    return -1;
                }
            }
        } else {
            NSError *error = nil;
            if (![fileManager createDirectoryAtPath:output_directory withIntermediateDirectories:YES attributes:nil error:&error] || error) {
                return -1;
            }
        }

        // Initialize library
        FSErrorCode errorCode = [FSLibrary initialize:sn key:key];
        if (errorCode != FSErrSuccess) {
            NSLog(@"Library Initialize Error: %ld", errorCode);
            return -1;
        }

        @try {
            FSPDFDoc *doc = [[FSPDFDoc alloc] initWithPath:input_file];
            [doc startLoad:@"" is_cache_stream:NO pause:nil];

            // Do some operation about PDF object.
            ObjectOperation(doc);
            NSString *save_pdf_patth = [output_directory stringByAppendingString:@"pdfobjects_addnewobjects.pdf"];
            [doc startSaveAs:save_pdf_patth save_flags:FSPDFDocSaveFlagNoOriginal pause:nil];

            // To remove some properties from catalog dictionary.
            RemoveCatalogKey(doc);
            save_pdf_patth = [output_directory stringByAppendingString:@"pdfobjects_removekeyfromcatalog.pdf"];
            [doc startSaveAs:save_pdf_patth save_flags:FSPDFDocSaveFlagNoOriginal pause:nil];
        }
        @catch (NSException *e) {
            NSLog(@"Unknown Exception, %@", e);
        }
    }
    [FSLibrary destroy];
    return 0;
}
