// Again, this is ported C++ code from gawgua's original Python code.
// All credits go to him, I just used DeepSeek to convert it to C++.

#include <iostream>
#include <format>
#include <Windows.h>
#include <libloaderapi.h>

// MuPDF structure definition
struct pdf_write_options {
    int do_incremental;
    int do_pretty;
    int do_ascii;
    int do_compress;
    int do_compress_images;
    int do_compress_fonts;
    int do_decompress;
    int do_garbage;
    int do_linear;
    int do_clean;
    int do_sanitize;
    int do_appearance;
    int do_encrypt;
    int dont_regenerate_id;
    int permissions;
    char opwd_utf8[128];
    char upwd_utf8[128];
    int do_snapshot;
    int do_preserve_metadata;
    int do_use_objstms;
    int compression_effort;
};

int main(const int argc, char* argv[])
{
	if (argc < 3) {
		std::cout << "usage: decypherer.exe <window id> <path> <output>" << std::endl;
		return 0;
	}
    // Arg 1
    auto window_id = argv[1];
    // Arg 2
    auto path = argv[2];
    // Arg 3
	const auto output = argv[3];

    const HMODULE mupdf = LoadLibraryA("mupdf-exp-dll-x86.dll");
    if (mupdf == nullptr) {
		std::cout << "error: failed to load MuPDF library" << std::endl;
		return 1;
    }

    // Define function pointers
    const auto fz_new_context_imp = reinterpret_cast<void* (*)(void *, void *, unsigned int, const char *)>(GetProcAddress(mupdf, "fz_new_context_imp"));
    const auto fz_register_document_handlers = reinterpret_cast<void* (*)(void *)>(GetProcAddress(mupdf, "fz_register_document_handlers"));
    const auto fz_open_document_w = reinterpret_cast<void* (*)(void *, const wchar_t *)>(GetProcAddress(mupdf, "fz_open_document_w"));
    const auto pdf_save_document = reinterpret_cast<void(*)(void *, void *, const char *, pdf_write_options *)>(GetProcAddress(mupdf, "pdf_save_document"));

    // Build argument path
    auto arg_path_str = std::format("#OCB#{}#{}", window_id, path);
    const std::wstring arg_path(arg_path_str.begin(), arg_path_str.end());

    // Create context
    void* ctx = fz_new_context_imp(nullptr, nullptr, 268435456, "1.16.1");
    fz_register_document_handlers(ctx);

    // Open document
    void* doc = fz_open_document_w(ctx, arg_path.c_str());

    // Set save options
    pdf_write_options opts = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, ~0,
        {}, {}, 0, 0, 0, 0
    };

    // Save document
    pdf_save_document(ctx, doc, output, &opts);
    FreeLibraryAndExitThread(mupdf, 0);
}
