#pragma once

#include <util/charset/wide.h>
#include <util/generic/string.h>
#include <util/generic/vector.h>
#include <util/string/split.h>

#include <library/cpp/string_utils/scan/scan.h>

namespace NWebmaster {
namespace NUtils {

inline TString ReplaceAll(TString text, const TString& s, const TString& d) {
    for(size_t index = 0; index = text.find(s, index), index != TString::npos;) {
        text.replace(index, s.length(), d);
        index += d.length();
    }
    return text;
}

inline void SplitString(const TString &value, const char *delimiter, TVector<TStringBuf> &parts) {
    ::SplitString(
        value.data(),
        value.data() + value.size(),
        TSetDelimiter<const char>(delimiter),
        TContainerConsumer<TVector<TStringBuf>>(&parts)
    );
}

template <class TChr>
inline size_t FastSplit(const TBasicStringBuf<TChr> &str, TChr sep, TVector<TBasicStringBuf<TChr>> &result) {
    result.clear();

    typedef TContainerConsumer< TVector< TBasicStringBuf<TChr> > > TConsumer;
    TConsumer consumer(&result);
    TSkipEmptyTokens<TConsumer> filter(&consumer);
    SplitString(str.data(), str.data() + str.size(), TCharDelimiter<const TChr>(sep), filter);

    return result.size();
}

inline TString Abbreviate(const TString &value, size_t maxWidth) {
    const static TUtf16String SUFFIX = u"...";
    Y_ASSERT(maxWidth > SUFFIX.size());
    const TUtf16String wideString = UTF8ToWide(value);
    if (wideString.size() < maxWidth) {
        return value;
    }
    return WideToUTF8(wideString.substr(0, maxWidth - SUFFIX.size()) + SUFFIX);
}

template <class F>
static inline void ScanKeyValue(TStringBuf s, TStringBuf sep, TStringBuf sepKeyVal, F&& f) {
    TStringBuf key, val;

    while (!s.empty()) {
        val = s.NextTok(sep);

        if (val.empty()) {
            continue; // && case
        }

        key = val.NextTok(sepKeyVal);

        if (val.IsInited()) {
            f(key, val); // includes empty keys
        }
    }
}

} //namespace NUtils
} //namespace NWebmaster
