#pragma once
#include <luna/CString.h>
#include <luna/Common.h>
#include <luna/StringView.h>
#include <luna/Types.h>

template <usize Size> class StaticString
{
  public:
    StaticString() = default;
    StaticString(const char* string)
    {
        adopt(string);
    }

    template <usize OtherSize> StaticString(const StaticString<OtherSize>& other)
    {
        adopt(other.chars());
    }

    void adopt(const char* string)
    {
        usize length = strlcpy(m_buffer, string, sizeof(m_buffer));
        if (length > Size) { m_length = Size; }
        else
            m_length = length;
    }

    void adopt(const char* string, usize length)
    {
        if (length > Size) length = Size;

        memcpy(m_buffer, string, length);

        m_buffer[length] = 0;
        m_length = length;
    }

    void adopt(StringView string)
    {
        usize length = strlcpy(m_buffer, string.chars(), min(sizeof(m_buffer), string.length() + 1));
        if (length > Size) { m_length = Size; }
        else
            m_length = length;
    }

    StaticString<Size>& operator=(const char* string)
    {
        adopt(string);
        return *this;
    }

    StaticString<Size>& operator=(StringView string)
    {
        adopt(string);
        return *this;
    }

    template <usize OtherSize> StaticString<Size>& operator=(const StaticString<OtherSize>& string)
    {
        if constexpr (OtherSize == Size)
        {
            if (this == &string) return *this;
        }

        adopt(string.chars());
        return *this;
    }

    const char* chars() const
    {
        return m_buffer;
    }

    char* data()
    {
        return m_buffer;
    }

    void set_length(usize len)
    {
        m_length = len;
    }

    usize length() const
    {
        return m_length;
    }

    void trim(StringView delim)
    {
        isize i = (isize)m_length;

        while (i--)
        {
            char c = m_buffer[i];
            if (!strchr(delim.chars(), c)) break;
        }

        i++;

        m_buffer[i] = '\0';

        m_length = (usize)i;
    }

  private:
    char m_buffer[Size + 1];
    usize m_length { 0 };
};