#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <uuid/uuid.h>

int main()
{
    std::ifstream input("alltypes.txt");

    if ( false == input.is_open() )
    {
        std::cerr << "Error: Could not open 'alltypes.txt'." << std::endl;
        return EXIT_FAILURE;
    }

    std::ofstream output( "visit_any.hpp" );

    if ( false == output.is_open() )
    {
        std::cerr << "Error: Could not create file.\n";
        return EXIT_FAILURE;
    }

    // Copy the contents of "allheaders.cpp" to the new file
    std::ifstream cppFile("allheaders.cpp");
    if ( false == cppFile.is_open() )
    {
        std::cerr << "Error: Could not open 'allheaders.cpp'." << std::endl;
        return EXIT_FAILURE;
    }

    std::string cppLine;
    while ( std::getline(cppFile, cppLine) )
    {
        output << cppLine << std::endl;
    }

    cppFile.close();

    output << "template<typename Any, typename T>\n"
              "using Lref_or_Rref = std::conditional_t< std::is_rvalue_reference_v<Any&&>, T&&, T& >;\n\n";

    output << "template<typename R, typename Visitor, class Any>\n"
              "requires std::is_same_v< std::any, std::remove_cvref_t<Any> >\n"
              "constexpr R visit(Visitor &&vis, Any &&arg)\n"
              "{\n";

    std::string line;
    long unsigned counter = -1;
    while ( std::getline(input, line) )
    {
        if ( std::string_view(line).contains("#") ) continue;

        output << "    if ( arg.type() == typeid(" << line << ") ) "
                  "return INVOKE<R>( std::forward<Visitor>(vis), std::any_cast< Lref_or_Rref<Any&&," << line << "> >(std::forward<Any>(arg)) );\n";
    }

    output << "}\n";
}


