#include <luna/NumberParsing.h>
#include <luna/PathParser.h>
#include <os/ArgumentParser.h>
#include <os/FileSystem.h>
#include <sys/stat.h>

static mode_t s_umask = 0;

static void read_umask()
{
    s_umask = umask(0);
}

Result<void> mkdir_recursively(StringView path, mode_t mode)
{
begin:
    auto rc = os::FileSystem::create_directory(path, mode);
    if (!rc.has_error()) return {};

    if (rc.error() == EEXIST) return {};
    if (rc.error() == ENOENT)
    {
        auto parent = TRY(PathParser::dirname(path));

        TRY(mkdir_recursively(parent.view(), (0777 & ~s_umask) | S_IWUSR | S_IXUSR));

        goto begin;
    }

    return rc.release_error();
}

Result<int> luna_main(int argc, char** argv)
{
    StringView path;
    StringView mode_string;
    bool recursive;

    os::ArgumentParser parser;
    parser.add_description("Create directories."_sv);
    parser.add_system_program_info("mkdir"_sv);
    parser.add_positional_argument(path, "path"_sv, true);
    parser.add_value_argument(mode_string, 'm', "mode"_sv, "set the mode for the newly created directory");
    parser.add_switch_argument(recursive, 'p', "parents"_sv,
                               "if parent directories do not exist, create them as well"_sv);
    parser.parse(argc, argv);

    read_umask();

    mode_t mode;

    if (mode_string.is_empty()) mode = 0777 & ~s_umask;
    else
        mode = (mode_t)parse_unsigned_integer(mode_string.chars(), nullptr, 8) & 01777;

    if (recursive)
    {
        TRY(mkdir_recursively(path, mode));
        return 0;
    }

    TRY(os::FileSystem::create_directory(path, mode));

    return 0;
}