#include "io.hpp"
#include "iterator.hpp"
#include "string.hpp"
#include "view.hpp"
#include "cpp.hpp"

#include <iostream>
#include <cstdlib>
#include <fstream>


enum {
    ARG_SELF,
    ARG_SRC,
    ARG_DST,

    MIN_ARGS = ARG_SRC+1,
};


#if 0
///////////////////////////////////////////////////////////////////////////////
void process (std::ostream &dst, const std::filesystem::path&);


///////////////////////////////////////////////////////////////////////////////
struct include {
    template <typename IteratorA, typename IteratorB>
    void
    operator() (std::ostream &dst, cruft::view<IteratorA,IteratorB> data)
    {
        if (data.size () < 3)
            throw std::invalid_argument ("invalid argument for include");

        if (data[0] != '"' || data[data.size()-1] != '"')
            throw std::invalid_argument ("invalid path specification");

        process (dst, {data.begin () + 1, data.end () - 1});
    }
};


///////////////////////////////////////////////////////////////////////////////
void
process (std::ostream &dst, const std::filesystem::path &src)
{
    auto data = cruft::slurp<char> (src);
    include handler;

    for (const auto &l: cruft::tokeniser (data.data (), '\n')) {
        if (l.empty () || l[0] != '#') {
            dst << l << '\n';
            continue;
        }

        auto space = std::find (l.begin (), l.end (), ' ');
        handler (dst, cruft::view{space+1,l.end()});
    }
}


///////////////////////////////////////////////////////////////////////////////
int
main (const int argc, const char **argv)
{
    if (argc < 2) {
        std::cerr << argv[ARG_SELF] << " <src> [dst]\n";
        return EXIT_FAILURE;
    }

    std::filesystem::path src = argv[ARG_SRC];

    if (argc == 3) {
        std::ofstream dst (argv[ARG_DST]);
        process (dst, src);
    } else {
        process (std::cout, src);
    };
};

#endif


int
main (const int argc, const char **argv)
{
    if (argc < 2) {
        std::cerr << argv[ARG_SELF] <<  " <src>\n";
        return EXIT_FAILURE;
    }

    cruft::cpp::processor cpp;
    cpp.process (std::cout, argv[ARG_SRC]);
}