#include <algorithm>
#include "./string.hpp"

namespace lsp::utils
{
    std::string Trim(const std::string& str)
    {
        size_t first = str.find_first_not_of(" \t\n\r");
        if (first == std::string::npos)
            return "";
        size_t last = str.find_last_not_of(" \t\n\r");
        return str.substr(first, last - first + 1);
    }

    std::string ToLower(const std::string& str)
    {
        std::string result = str;
        std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return std::tolower(c); });
        return result;
    }

    std::string ToUpper(const std::string& str)
    {
        std::string result = str;
        std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return std::toupper(c); });
        return result;
    }

    bool StartsWith(const std::string& str, const std::string& prefix)
    {
        if (prefix.size() > str.size())
            return false;
        return str.compare(0, prefix.size(), prefix) == 0;
    }

    bool EndsWith(const std::string& str, const std::string& suffix)
    {
        if (suffix.size() > str.size())
            return false;
        return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
    }

    // ==================== 大小写不敏感比较 ====================
    bool IEquals(const std::string& a, const std::string& b)
    {
        if (a.size() != b.size())
            return false;

        return std::equal(a.begin(), a.end(), b.begin(), [](unsigned char ca, unsigned char cb) {
            return std::tolower(ca) == std::tolower(cb);
        });
    }

    bool IStartsWith(const std::string& str, const std::string& prefix)
    {
        if (prefix.size() > str.size())
            return false;

        for (size_t i = 0; i < prefix.size(); ++i)
        {
            if (std::tolower(static_cast<unsigned char>(str[i])) !=
                std::tolower(static_cast<unsigned char>(prefix[i])))
                return false;
        }
        return true;
    }

    bool IEndsWith(const std::string& str, const std::string& suffix)
    {
        if (suffix.size() > str.size())
            return false;

        size_t offset = str.size() - suffix.size();
        for (size_t i = 0; i < suffix.size(); ++i)
        {
            if (std::tolower(static_cast<unsigned char>(str[offset + i])) !=
                std::tolower(static_cast<unsigned char>(suffix[i])))
                return false;
        }
        return true;
    }

    int ICompare(const std::string& a, const std::string& b)
    {
        size_t min_len = std::min(a.size(), b.size());

        for (size_t i = 0; i < min_len; ++i)
        {
            int ca = std::tolower(static_cast<unsigned char>(a[i]));
            int cb = std::tolower(static_cast<unsigned char>(b[i]));

            if (ca != cb)
                return ca - cb;
        }

        // 长度不同
        if (a.size() < b.size())
            return -1;
        if (a.size() > b.size())
            return 1;

        return 0;
    }

    size_t IHash(const std::string& str)
    {
        size_t hash = 0;
        for (unsigned char c : str)
            hash = hash * 31 + std::tolower(c);
        return hash;
    }
}
