#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "../dynapdf/dynapdf.h"

using namespace DynaPDF;

// Error callback function.
SI32 PDF_CALL PDFError(const void* Data, SI32 ErrCode, const char* ErrMessage, SI32 ErrType)
{
   // The error type is a bitmask, see help file for further information.
   if (ErrType & E_WARNING)
      printf("Warning: %s\n", ErrMessage);
   else if (ErrType & E_SYNTAX_ERROR)
      printf("Syntax error!: %s\n", ErrMessage);
   else if (ErrType & E_VALUE_ERROR)
      printf("Value error: %s\n", ErrMessage);
   else if (ErrType & E_FONT_ERROR)
      printf("TrueType font error!: %s\n", ErrMessage);
   else if (ErrType & E_FILE_ERROR)
      printf("File error: %s\n", ErrMessage);
   else if (ErrType & E_FATAL_ERROR)
      printf("Fatal error: %s\n", ErrMessage);
   else
      printf("%s\n", ErrMessage);
   return 0; // any other return value breaks processing!
}

int main(void)
{
   void* pdf = pdfNewPDF();
   if (!pdf) return 2; // Out of memory?
   
   // On macOS we use UTF-8 encoded source files. String literals are UTF-8 encoded too in this case.
   // We must tell DynaPDF that Ansi strings are UTF-8 encoded.
   pdfSetGStateFlags(pdf, gfAnsiStringIsUTF8, false);
   
   char outFile[] = "acroform.pdf";
   // Error messages and warnings are passed to the callback function.
   pdfSetOnErrorProc(pdf, NULL, PDFError);
   if (pdfCreateNewPDFA(pdf, outFile) < 0)
   {
      pdfDeletePDF(pdf);
      return 1;
   }
   pdfSetDocInfo(pdf, diCreator, "C++ Example Project");
   pdfSetDocInfo(pdf, diSubject, "How to Edit an existing pdf file");
   pdfSetDocInfo(pdf, diTitle, "Edit pdf files");
   pdfSetDocInfo(pdf, diAuthor, "Jens Boschulte");
   pdfSetViewerPreferences(pdf, vpDisplayDocTitle, avNone);
   // Conversion of pages to templates is normally not required. Templates are required if
   // the page should be scaled or used multiple times in a document, e.g. as background.
   // See help file for further information.
   pdfSetImportFlags(pdf, ifImportAll + ifImportAsPage);
   if (pdfOpenImportFile(pdf, "test_files/taxform.pdf", ptOpen, NULL) < 0)
   {
      pdfDeletePDF(pdf);
      return 1;
   }
   pdfImportPDFFile(pdf, 1, 1.0, 1.0);

   pdfEditPage(pdf, 1);

   pdfSetCheckBoxChar(pdf, ccCross4);
   pdfSetLineWidth(pdf, 0.0);
   pdfSetFieldBorderColor(pdf, NO_COLOR);

   SI32 f = pdfCreateRadioButton(pdf, "AntragsArt", "EinkommensSteuerErklärung", false, -1, 68.5, 745.0, 16.0, 16.0);
   pdfCreateCheckBox(pdf, NULL, "Sparzulage", false, f, 68.5, 721.0, 16.0, 16.0);
   pdfCreateCheckBox(pdf, NULL, "VerlustErklärung", false, f, 247.5, 721.0, 16.0, 16.0);

   pdfSetFont(pdf, "Courier", fsNone, 12.0, true, cp1252);
   pdfCreateTextField(pdf, "Finanzamt", -1, false, 0, 71.0, 698.0, 356.0, 16.0);
   pdfCreateTextField(pdf, "Steuernummer", -1, false, 14, 71.0, 673.5, 147.0, 16.0);
   pdfCreateTextField(pdf, "Finanzamt_alt", -1, false, 0, 269.5, 673.5, 157.0, 16.0);

   pdfCreateCheckBox(pdf, "Rückerstattung", "Ja", true, -1, 428.5, 673.5, 15.0, 15.0);

   pdfCreateTextField(pdf, "Telefon", -1, false, 0, 285.5, 649.0, 143.0, 16.0);

   pdfSetCharacterSpacing(pdf, 7.2);
   f = pdfCreateTextField(pdf, "Name", -1, false, 25, 71.0, 625.0, 357.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);
   f = pdfCreateTextField(pdf, "Vorname", -1, false, 25, 71.0, 601.5, 357.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);
   f = pdfCreateTextField(pdf, "Geburtsdatum", -1, false, 10, 71.0, 577.5, 113.0, 16.0);
   // Create a custom date format action -> input example: 13.05.1971 or 13-05-1971 or 13/05/1971
   // Two actions are required, one for the event onKeyStroke and one for the event onFormat.
   SI32 keyStrokeAct = pdfCreateJSActionA(pdf, "AFDate_KeystrokeEx(\"ddmmyyyy\");");
   SI32 formatAct = pdfCreateJSActionA(pdf, "AFDate_FormatEx(\"ddmmyyyy\");");

   // Add both actions to the field
   pdfAddActionToObj(pdf, otField, oeOnKeyStroke, keyStrokeAct, f);
   pdfAddActionToObj(pdf, otField, oeOnFormat, formatAct, f);

   pdfSetCharacterSpacing(pdf, 0.0);
   f = pdfCreateComboBox(pdf, "Religion", false, -1, 186.0, 577.5, 70.0, 16.0);
   pdfAddValToChoiceFieldA(pdf, f, "keine", "keine", true);
   pdfAddValToChoiceFieldA(pdf, f, "Evang", "Evang.", false);
   pdfAddValToChoiceFieldA(pdf, f, "Kath", "Kath.", false);
   pdfAddValToChoiceFieldA(pdf, f, "andere", "andere", false);

   pdfCreateTextField(pdf, "Beruf", -1, false, 0, 258.0, 577.5, 171.0, 16.0);

   pdfSetCharacterSpacing(pdf, 7.2);
   f = pdfCreateTextField(pdf, "Strasse", -1, false, 25, 72.0, 553.5, 356.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);
   f = pdfCreateTextField(pdf, "PLZ", -1, false, 5, 72.0, 529.5, 69.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);
   pdfSetNumberFormat(pdf, f, dsNoneDot, 0, nsRed, NULL, false);

   f = pdfCreateTextField(pdf, "Wohnort", -1, false, 20, 144.0, 529.5, 284.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);

   pdfSetCharacterSpacing(pdf, 0.0);
   pdfSetFontA(pdf, "Courier", fsNone, 11.0, true, cp1252);

   f = pdfCreateTextField(pdf, "VerheiratetSeit", -1, false, 10, 70.0, 506.0, 71.0, 16.0);
   // We need another date format here. The date should be delimited with a dot.
   SI32 keyStrokeAct2 = pdfCreateJSActionA(pdf, "AFDate_KeystrokeEx(\"dd.mm.yyyy\");");
   SI32 formatAct2 = pdfCreateJSActionA(pdf, "AFDate_FormatEx(\"dd.mm.yyyy\");");
   pdfAddActionToObj(pdf, otField, oeOnKeyStroke, keyStrokeAct2, f);
   pdfAddActionToObj(pdf, otField, oeOnFormat, formatAct2, f);

   f = pdfCreateTextField(pdf, "VerwitwetSeit", -1, false, 10, 142.0, 506.0, 71.0, 16.0);
   pdfAddActionToObj(pdf, otField, oeOnKeyStroke, keyStrokeAct2, f);
   pdfAddActionToObj(pdf, otField, oeOnFormat, formatAct2, f);

   f = pdfCreateTextField(pdf, "GeschiedenSeit", -1, false, 10, 214.0, 506.0, 70.0, 16.0);
   pdfAddActionToObj(pdf, otField, oeOnKeyStroke, keyStrokeAct2, f);
   pdfAddActionToObj(pdf, otField, oeOnFormat, formatAct2, f);

   f = pdfCreateTextField(pdf, "GetrenntSeit", -1, false, 10, 286.0, 506.0, 142.0, 16.0);
   pdfAddActionToObj(pdf, otField, oeOnKeyStroke, keyStrokeAct2, f);
   pdfAddActionToObj(pdf, otField, oeOnFormat, formatAct2, f);

   pdfSetCharacterSpacing(pdf, 7.2);
   pdfSetFontA(pdf, "Courier", fsNone, 12.0, true, cp1252);
   f = pdfCreateTextField(pdf, "EhefrauVorname", -1, false, 25, 72.0, 458.0, 356.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);
   f = pdfCreateTextField(pdf, "EhefrauName", -1, false, 25, 72.0, 434.0, 356.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);

   f = pdfCreateTextField(pdf, "EhefrauGeburtdatum", -1, false, 10, 72.0, 410.0, 113.0, 16.0);
   // Add both actions to the field
   pdfAddActionToObj(pdf, otField, oeOnKeyStroke, keyStrokeAct, f);
   pdfAddActionToObj(pdf, otField, oeOnFormat, formatAct, f);

   pdfSetCharacterSpacing(pdf, 0.0);
   f = pdfCreateComboBox(pdf, "EhefrauReligion", false, -1, 186.0, 410.0, 70.0, 16.0);
   pdfAddValToChoiceFieldA(pdf, f, "keine", "keine", true);
   pdfAddValToChoiceFieldA(pdf, f, "Evang", "Evang.", false);
   pdfAddValToChoiceFieldA(pdf, f, "Kath", "Kath.", false);
   pdfAddValToChoiceFieldA(pdf, f, "andere", "andere", false);

   pdfCreateTextField(pdf, "EhefrauBeruf", -1, false, 0, 258.0, 410.0, 171.0, 16.0);
   pdfCreateTextField(pdf, "EhefrauStrasse", -1, false, 49, 71.0, 385.5, 357.0, 16.0);

   f = pdfCreateRadioButton(pdf, "Veranlagung", "Zusammen", false, -1, 68.5, 362.0, 16.0, 16.0);
   pdfCreateCheckBox(pdf, NULL, "Getrennt", false, f, 140.0, 362.0, 16.0, 16.0);
   pdfCreateCheckBox(pdf, NULL, "Eheschliessung", false, f, 212.0, 362.0, 16.0, 16.0);

   f = pdfCreateRadioButton(pdf, "Guetergemeinschaft", "Ja", false, -1, 355.5, 362.0, 16.0, 16.0);
   pdfCreateCheckBox(pdf, NULL, "Nein", false, f, 391.5, 362.0, 16.0, 16.0);

   pdfSetCharacterSpacing(pdf, 7.2);
   f = pdfCreateTextField(pdf, "Konto", -1, false, 10, 71.0, 313.5, 142.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);
   pdfSetNumberFormat(pdf, f, dsNoneDot, 0, nsRed, NULL, false);
   f = pdfCreateTextField(pdf, "BLZ", -1, false, 8, 287.0, 313.5, 112.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);
   pdfSetNumberFormat(pdf, f, dsNoneDot, 0, nsRed, NULL, false);

   f = pdfCreateTextField(pdf, "Bank", -1, false, 25, 71.0, 290.0, 356.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);

   pdfCreateCheckBox(pdf, "AbwInhaber", "Ja", false, -1, 68.5, 265.0, 16.0, 16.0);
   f = pdfCreateTextField(pdf, "AbwKontoInhaber", -1, false, 21, 130.0, 265.5, 298.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);

   f = pdfCreateTextField(pdf, "AbwEmpfName", -1, false, 25, 71.0, 218.0, 357.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);
   f = pdfCreateTextField(pdf, "AbwEmpfVorname", -1, false, 25, 71.0, 194.0, 357.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);
   f = pdfCreateTextField(pdf, "AbwEmpfStrasse", -1, false, 25, 71.0, 170.0, 357.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);
   f = pdfCreateTextField(pdf, "AbwEmpfPLZ", -1, false, 5, 71.0, 146.0, 72.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);
   pdfSetNumberFormat(pdf, f, dsNoneDot, 0, nsRed, NULL, false);

   f = pdfCreateTextField(pdf, "AbwEmpfWohnort", -1, false, 20, 144.0, 146.5, 284.0, 16.0);
   pdfSetFieldFlags(pdf, f, ffComb, false);

   // Add a reset button to the form
   pdfSetFieldBorderColor(pdf, PDF_BLACK);
   pdfSetFieldBackColor(pdf, PDF_MOGREEN);
   pdfSetLineWidth(pdf, 1.0);
   pdfSetFont(pdf, "Helvetica", fsBold, 12.0, true, cp1252);
   f = pdfCreateButtonA(pdf, "Reset", "Zurücksetzen", -1, 440.0, 730.0, 120.0, 25.0);
   pdfSetFieldBorderStyle(pdf, f, bsBevelled);
   SI32 act = pdfCreateResetAction(pdf);
   pdfAddActionToObj(pdf, otField, oeOnMouseUp, act, f);

   time_t t;
   struct tm* now;
   time(&t);
   now = gmtime(&t);
   char buf[64];
   snprintf(buf, 64, "%02d.%02d.%d", now->tm_mday, now->tm_mon + 1, now->tm_year + 1900);

   pdfSetCharacterSpacing(pdf, 0.0);
   pdfSetFont(pdf, "Courier", fsNone, 12.0, true, cp1252);
   pdfWriteText(pdf, 53.0, 48.0, buf);

   pdfSetFillColor(pdf, PDF_RGB(0xFF, 0x66, 0x66));
   pdfSetFont(pdf, "Helvetica", fsBold, 22.0, false, cp1252);
   pdfWriteText(pdf, 340.0, 70.0, "www.dynaforms.de");

   pdfSetLineWidth(pdf, 0.0);
   pdfSetLinkHighlightMode(pdf, hmPush);
   pdfSetAnnotFlags(pdf, afReadOnly);
   pdfWebLink(pdf, 340.0, 64.0, 204.0, 22.0, "http://www.dynaforms.de");

   char AlertScript[] =
      "if (app.viewerVersion >= 7.0 && app.viewerVersion < 8.0)\n"
      "{\n"
      "app.alert(\"Due to bugs in Acrobat 7.0 character spacing does not work"
      " in text fields. We use the flag ffComb instead which is supported since"
      " Acrobat 6.0. However, if the field's format is controled by a JavaScript"
      " Action, we cannot set the flag because Acrobat 6.0 is then unable"
      " to display the field's text. Acrobat 7.0 has problems to place the"
      " the cursor in such fields but the final format will be correctly applied."
      " The problem is that if the form should work with Acrobat 6.0 we cannot set"
      " the flag ffComb to the date fields. It is also impossible to get the same"
      " result as with character spacing with the flag ffComb. So, what can we do to make the"
      " form compatible to all Acrobat versions? I really don't know! The easiest way"
      " would be to avoid the usage of such date formats.\");\n"
      "}";

   pdfAddJavaScript(pdf, "VersionCheck", AlertScript);

   pdfEndPage(pdf);
   pdfCloseFile(pdf);
   pdfDeletePDF(pdf);
   printf("PDF file %s successfully created!\n", outFile);
   return 0;
}
