// 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 add table to PDF document.

#include "FSPDFObjC.h"


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";

NSString *output_directory = @"../output_files/electronictable/";


FSDateTime *GetLocalDateTime() {
    time_t t = time(NULL);
    struct tm *rime = localtime(&t);
    tzset();
    int timezone_hour = (int) timezone / 3600 * -1;
    int timezone_minute = (abs((int) timezone) % 3600) / 60;

    FSDateTime *datetime = [[FSDateTime alloc] initWithYear:(rime->tm_year + 1900) month:(rime->tm_mon + 1) day:(rime->tm_mday) hour:(rime->tm_hour) minute:(rime->tm_min) second:(rime->tm_sec) milliseconds:0 utc_hour_offset:timezone_hour utc_minute_offset:timezone_minute];

    return datetime;
}

NSString *DateTimeToString(const FSDateTime *datetime) {
    NSString *s_datetime = [[NSString alloc] initWithFormat:@"%d/%d/%d-%d:%d:%d %@%d:%d", datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second, datetime.utc_hour_offset > 0 ? @"+" : @"-", datetime.utc_hour_offset, datetime.utc_minute_offset];
    return s_datetime;
}

FSRichTextStyle *GetTableTextStyle(int index){
    FSRichTextStyle* style = [[FSRichTextStyle alloc] init];
    FSFont* d_font = [[FSFont alloc] initWithFont_id:FSFontStdIDHelvetica];
    [style setFont:d_font];
    [style setText_size:10];
    [style setText_alignment:FSAlignmentLeft];
    [style setText_color:0x000000];
    [style setIs_bold:NO];
    [style setIs_italic:NO];
    [style setIs_underline:NO];
    [style setIs_strikethrough:NO];
    [style setMark_style:FSRichTextStyleCornerMarkNone];

    switch (index) {
        case 1:
            [style setText_alignment:FSAlignmentCenter];
            break;
        case 2: {
            [style setText_alignment:FSAlignmentRight];
            [style setText_color:0x00FF00];
            break;
        }
        case 3:
            [style setText_size:15];
            break;
        case 4: {
            FSFont* font = [[FSFont alloc] initWithName:@"Times New Roman" styles:0 charset:FSFontCharsetANSI weight:0];
            [style setFont:font];
            [style setText_color:0xFF0000];
            [style setText_alignment:FSAlignmentRight];
            break;
        }
        case 5: {
            FSFont* font = [[FSFont alloc] initWithName:@"Times New Roman" styles:0 charset:FSFontCharsetANSI weight:0];
            [style setFont:font];
            [style setIs_bold:YES];
            [style setText_alignment:FSAlignmentRight];
            break;
        }
        case 6: {
            [style setIs_bold:YES];
            [style setIs_italic:YES];
            break;
        }
        case 7: {
            [style setIs_bold:YES];
            [style setIs_italic:YES];
            [style setText_alignment:FSAlignmentCenter];
            break;
        }
        case 8: {
            [style setIs_underline:YES];
            [style setText_alignment:FSAlignmentRight];
            break;
        }
        case 9:
            [style setIs_strikethrough:YES];
            break;
        case 10:
            [style setMark_style:FSRichTextStyleCornerMarkSubscript];
        case 11:
            [style setMark_style:FSRichTextStyleCornerMarkSuperscript];
        default:
            break;
    }
    return style;
}


NSString *GetTableCellText(int index) {
    switch (index) {
    case 0:
        return @"Reference style";
    case 1 :
        return @"Alignment center";
    case 2:
        return @"Green text color and alignment right";
    case 3:
        return @"Text font size 15";
    case 4:
        return @"Red text color, Times New Roman font and alignment right";
    case 5:
        return @"Bold, Times New Roman font and alignment right";
    case 6:
        return @"Bold and italic";
    case 7:
        return @"Bold, italic and alignment center";
    case 8:
        return @"Underline and alignment right";
    case 9:
        return @"Strikethrough";
    case 10:
        return @"CornerMarkSubscript";
    case 11:
        return @"CornerMarkSuperscript";
    default:
        return @" ";
    }
}


void AddElectronicTable(FSPDFPage *page){
    {
        // Add a spreadsheet with 4 rows and 3 columns
        int index = 0;
        FSTableCellDataArray *cell_array = [[FSTableCellDataArray alloc] init];
        for (int row = 0; row < 4; row++) {
            FSTableCellDataColArray *col_array = [[FSTableCellDataColArray alloc] init];
            for (int col = 0; col < 3; col++) {
                FSRichTextStyle *style = GetTableTextStyle(index);
                NSString *cell_text = GetTableCellText(index);
                FSImage *cell_image = [[FSImage alloc] init];
                FSRectF* rect = [[FSRectF alloc] init];
                FSTableCellData *cell_data = [[FSTableCellData alloc] initWithCell_text_style:style cell_fill_color:0xFFFFFFFF cell_text:cell_text cell_image:cell_image cell_margin:rect];
                [col_array add:cell_data];
                index = index + 1;
            }
            [cell_array add:col_array];
        }

        float width = [page getWidth];
        float height = [page getHeight];
        float right = width - 100;
        float top = height - 100;
        FSRectF* rect = [[FSRectF alloc] initWithLeft1:100 bottom1:550 right1:right top1:top];
        FSTableBorderInfo *outside_border_left = [[FSTableBorderInfo alloc] init];
        outside_border_left.line_width = 1;
        FSTableBorderInfo *outside_border_right = [[FSTableBorderInfo alloc] init];
        outside_border_right.line_width = 1;
        FSTableBorderInfo *outside_border_top = [[FSTableBorderInfo alloc] init];
        outside_border_top.line_width = 1;
        FSTableBorderInfo *outside_border_bottom = [[FSTableBorderInfo alloc] init];
        outside_border_bottom.line_width = 1;
        FSTableBorderInfo *inside_border_col_info = [[FSTableBorderInfo alloc] init];
        inside_border_col_info.line_width = 1;
        FSTableBorderInfo *inside_border_row_info = [[FSTableBorderInfo alloc] init];
        inside_border_row_info.line_width = 1;
        FSTableCellIndexArray* merge_cells = [[FSTableCellIndexArray alloc] init];
        FSFloatArray* row_height_array = [[FSFloatArray alloc] init];
		FSFloatArray* col_width_array = [[FSFloatArray alloc] init];
        FSTableData* data = [[FSTableData alloc] initWithRect:rect row_count:4 col_count:3 outside_border_left:outside_border_left outside_border_right:outside_border_right outside_border_top:outside_border_top outside_border_bottom:outside_border_bottom inside_border_row:inside_border_col_info inside_border_col:inside_border_row_info merge_cells:merge_cells row_height_array:row_height_array col_width_array:col_width_array];
        
        [FSTableGenerator addTableToPage:page data:data cell_array:cell_array];
    }

    {
        //Add a spreadsheet with 5 rows and 6 columns
        FSTableCellDataArray *cell_array = [[FSTableCellDataArray alloc] init];
        for (int row = 0; row < 5; row++) {
            FSTableCellDataColArray *col_array = [[FSTableCellDataColArray alloc] init];
            for (int col = 0; col < 6; col++) {
                FSRichTextStyle *style = GetTableTextStyle(row);
                NSString *cell_text = @" ";
                switch (col) {
                    case 0:
                        cell_text = @"First column";
                        break;
                    case 1:
                        cell_text = @"Second column";
                        break;
                    case 2:
                        cell_text = @"Third column";
                        break;
                    case 3:
                        cell_text = @"Fourth column";
                        break;
                    case 4:
                        cell_text = @"Fifth column";
                        break;
                    case 5:
                        cell_text = DateTimeToString(GetLocalDateTime());
                        break;
                    default:
                        break;
                }
                FSImage *cell_image = [[FSImage alloc] init];
                FSRectF* rect = [[FSRectF alloc] init];
                FSTableCellData *cell_data = [[FSTableCellData alloc] initWithCell_text_style:style cell_fill_color:0xFFFFFFFF cell_text:cell_text cell_image:cell_image cell_margin:rect];
                [col_array add:cell_data];   
            }
            [cell_array add:col_array];
        }

        float width = [page getWidth];
        float height = [page getHeight];
        float right = width - 10;
        float top = height - 350;
        FSRectF* rect = [[FSRectF alloc] initWithLeft1:10 bottom1:200 right1:right top1:top];
        FSTableBorderInfo *outside_border_left = [[FSTableBorderInfo alloc] init];
        outside_border_left.line_width = 1;
        FSTableBorderInfo *outside_border_right = [[FSTableBorderInfo alloc] init];
        outside_border_right.line_width = 1;
        FSTableBorderInfo *outside_border_top = [[FSTableBorderInfo alloc] init];
        outside_border_top.line_width = 1;
        FSTableBorderInfo *outside_border_bottom = [[FSTableBorderInfo alloc] init];
        outside_border_bottom.line_width = 1;
        FSTableBorderInfo *inside_border_col_info = [[FSTableBorderInfo alloc] init];
        inside_border_col_info.line_width = 1;
        FSTableBorderInfo *inside_border_row_info = [[FSTableBorderInfo alloc] init];
        inside_border_row_info.line_width = 1;
        FSTableCellIndexArray* merge_cells = [[FSTableCellIndexArray alloc] init];
		FSFloatArray* row_height_array = [[FSFloatArray alloc] init];
		FSFloatArray* col_width_array = [[FSFloatArray alloc] init];
        FSTableData* data = [[FSTableData alloc] initWithRect:rect row_count:5 col_count:6 outside_border_left:outside_border_left outside_border_right:outside_border_right outside_border_top:outside_border_top outside_border_bottom:outside_border_bottom inside_border_row:inside_border_col_info inside_border_col:inside_border_row_info merge_cells:merge_cells row_height_array:row_height_array col_width_array:col_width_array];
        [FSTableGenerator addTableToPage:page data:data cell_array:cell_array];
    }
}

int main(int argc, const char *argv[]) {
    @autoreleasepool {
       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] init];
            FSPDFPage *page = [doc insertPageWithType:0 size:FSPDFPageSizeLetter];
            AddElectronicTable(page);

            NSString *output_file = [[NSString alloc] initWithFormat:@"%@%@", output_directory, @"electronictable_result.pdf"];
            [doc saveAs:output_file save_flags:FSPDFDocSaveFlagNoOriginal];
            NSLog(@"electronictable demo.");
        }
        @catch (NSException *exception) {
            NSLog(@"Unknown Exception, %@", exception);
            return -1;
        }
    }
    [FSLibrary destroy];
    return 0;
}
