#pragma once
#include <luna/Result.h>
#include <luna/StringView.h>
#include <stdarg.h>

class String
{
    typedef char* Iterator;
    typedef const char* ConstIterator;

  public:
    String(char* c_str);
    String(char* c_str, usize length);

    String();

    String(String&&);
    String(const String&) = delete;

    String& operator=(String&&);
    String& operator=(const String&) = delete;

    ~String();

    Result<String> clone() const;

    Result<String> substring(usize begin, usize size) const;

    Result<Vector<String>> split(StringView delim) const;
    Result<Vector<String>> split_once(char delim) const
    {
        return view().split_once(delim);
    }

    void trim(StringView delim);

    static Result<String> format(const String& fmt, ...);
    static Result<String> format(StringView fmt, ...);

    static Result<String> from_cstring(const char* str);

    const char* chars() const
    {
        return m_inline ? m_inline_storage : m_string;
    }

    usize length() const
    {
        return m_length;
    }

    bool is_empty() const
    {
        return m_length == 0;
    }

    StringView view() const
    {
        return { chars(), m_length };
    }

    const char& operator[](usize) const;

    Iterator begin()
    {
        return m_inline ? m_inline_storage : m_string;
    }

    ConstIterator begin() const
    {
        return chars();
    }

    Iterator end()
    {
        return begin() + m_length;
    }

    ConstIterator end() const
    {
        return begin() + m_length;
    }

  private:
    union {
        char* m_string { nullptr };
        char m_inline_storage[sizeof(char*)];
    };

    bool m_inline { true };

    usize m_length { 0 };

    static Result<String> vformat(StringView fmt, va_list ap);
};