#pragma once
#include <luna/StringView.h>
#include <luna/Vector.h>

namespace os
{
    class ArgumentParser
    {
      public:
        ArgumentParser();

        void add_description(StringView description);

        Result<void> add_positional_argument(StringView& out, StringView name, bool required);
        Result<void> add_positional_argument(StringView& out, StringView name, StringView fallback);

        Result<void> add_switch_argument(bool& out, char short_flag, StringView long_flag, StringView help = {});

        Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, bool value_required,
                                        StringView help = {});
        Result<void> add_value_argument(StringView& out, char short_flag, StringView long_flag, StringView fallback,
                                        StringView help = {});

        Result<Vector<StringView>> parse(int argc, char* const* argv);

        struct ProgramInfo
        {
            StringView name;
            StringView version;
            StringView copyright;
            StringView license;
            StringView authors;
            StringView package;
        };

        void add_program_info(ProgramInfo info);

        /* Used from programs that are part of the Luna source tree, to add the same version info for all programs.
         * Should not be used otherwise. */
        void add_system_program_info(StringView name);

      private:
        struct PositionalArgument
        {
            StringView* out;
            StringView name;
            bool required;
            StringView fallback;
        };

        struct SwitchArgument
        {
            bool* out;
            char short_flag;
            StringView long_flag;
            StringView help;
        };

        struct ValueArgument
        {
            StringView* out;
            char short_flag;
            StringView long_flag;
            bool required;
            StringView fallback;
            StringView help;
        };

        Result<void> usage(StringView program_name);
        void short_usage(StringView program_name);

        void version();

        Vector<PositionalArgument> m_positional_args;
        Vector<SwitchArgument> m_switch_args;
        Vector<ValueArgument> m_value_args;
        ProgramInfo m_program_info;
        StringView m_description = {};
        bool m_add_short_help_flag { false };
        bool m_add_long_help_flag { false };
        bool m_add_short_version_flag { false };
        bool m_add_long_version_flag { false };
    };
}