#pragma once
#include <string>
#include <vector>

namespace ArgumentParser {

enum class Type {
    INT,
    STRING,
    BOOL,
    HELP,
};

class Args {
public:
    Args();
    Args(const std::string param);
    Args(const char short_param, const std::string param);
    ~Args() {};
    virtual Type GetType() const = 0;

    Args& MultiValue();
    Args& MultiValue(const int min_args_count);
    bool GetFlagMultiValue();

    Args& Positional();
    bool GetFlagPositional();

    void MultiArgsCount(); 
    int GetMultiArgsCount();
    int GetMinArgsCount();

    void AddAllValues(const std::string value);
    int GetIndexedValue(const int ind);

    void Description(const std::string description);


    bool flag_positional_ = false;

    bool flag_multi_value_ = false;
    int min_args_count_;
    int multi_args_count_ = 0;

    std::vector<int> all_values_;

    std::string description_;

};

class Int : public Args {
public:
    Type GetType() const override {
        return Type::INT;
    }
    void StoreValues(std::vector<int>& store_values);
    void AddStoreValues(const std::string value);
    bool GetFlagStoreValues();
    std::string GetParam();
    char GetShortParam();
    bool GetFlagShortParam();
    void PutValue(const std::string value);
    std::string GetValue();

    std::vector<int>* store_values_;
    std::string param_;
    char short_param_;
    bool flag_short_param_ = false;
    bool flag_store_values_ = false;
    std::string value_;
};

class String : public Args {
public:
    Type GetType() const override {
        return Type::STRING;
    }
    std::string GetParam();
    char GetShortParam();
    bool GetFlagShortParam();
    String& Default(const char* value);
    std::string GetDefaultValue();

    void StoreValue(std::string& value);
    void AddStoreValue(const std::string value);
    bool GetFlagStoreValue();
    
    std::string param_;
    char short_param_;
    bool flag_short_param_ = false;
    std::string* store_value_;
    std::string default_value_;

    bool flag_store_value_ = false;
};

class Bool : public Args {
public:
    Type GetType() const override {
        return Type::BOOL;
    }
    Bool& Default(const bool flag);
    bool GetFlagDefaultFlag();
    void StoreValue(bool& flag);
    bool GetFlagStoreFlag();
    void AddStoreFlag(const bool flag);
    void AddFlags(const char short_flag, const std::string flag);
    void AddFlag(const std::string flag);
    std::string GetFlag();
    bool GetIsFlag();
    char GetShortFlag();

    std::string flag_;
    char short_flag_;
    bool is_flag_ = false;
    bool default_flag_;
    bool flag_default_flag_ = false;
    bool* store_flag_;
    bool flag_store_flag_ = false;
};

class Help : public Args {
public:
    Type GetType() const override {
        return Type::HELP;
    }
    std::string GetHelp();
    char GetShortHelp();
    void FlagHelp();
    bool GetFlagHelp();

    void Description(const std::string description);
    char short_help_;
    std::string help_;
    std::string description_;
    bool flag_help_ = false;
};

};Help& ArgParser::AddHelp(const char short_help, const std::string help, const std::string description) {
        Help* new_help = new Help();
        all_.push_back(new_help);
        return *new_help;
    } требуется спецификатор типаC/C++(79)