#ifndef STRING_HPP
#define STRING_HPP

#include "symbol.hpp"
#include "scalar.hpp"

class string : public symbol_impl_proxy<string> {
public :
    std::string value;

    struct unquoted {};

    string() = default;
    explicit string(const std::string& s);
    explicit string(std::string&& s);
    explicit string(const std::string& s, unquoted);
    explicit string(std::string&& s, unquoted);

    string* clone() const override;
    symbol_impl* evaluate(const interpreter_context& context) const override;
    std::string serialize(const interpreter_context& context) const override;
    static const std::string& static_type_name();
    bool is_litteral() const override;
    std::pair<std::size_t,std::size_t> priority(const interpreter_context&) const override;

    static void reg(interpreter_context& context);
};

template<>
struct type_traits<std::string> {
    static std::string serialize(const std::string& s, const interpreter_context& context);

    static const std::string type_name;

    using symbol_t = string;
    static const bool is_numeric = false;
};

#include <vector>
#include <sstream>

std::string trim(const std::string& str);
std::string trim(const std::string& str, const std::string& chars);
std::vector<std::string> split_token(const std::string& str, const std::string& token);
std::vector<std::string> split(const std::string& str, const std::string& tokens);
void replace(std::string& str, const std::string& token, const std::string& rep);
template<typename T>
std::string to_string(const T& t) {
    std::stringstream ss;
    ss << t;
    return ss.str();
}
template<typename T>
std::string to_string(const std::vector<T>& t, const std::string& sep = ",") {
    std::stringstream ss;
    for (std::size_t i = 0; i < t.size(); ++i) {
        if (i != 0) ss << sep;
        ss << t[i];
    }
    return ss.str();
}

#endif
