#include <util/generic/yexception.h>
#include <util/charset/wide.h>

#include "regex.h"

namespace NWebmaster {

TRegularExpression::TRegularExpression(const TString &regex) {
    const char *error;
    int erroffset;

    re = pcre_compile(regex.data(), PCRE_MULTILINE, &error, &erroffset, nullptr);

    if (!re) {
        ythrow yexception() << "pcre_compile failed (offset: " << erroffset << "), " << error;
    }
}

TRegularExpression::~TRegularExpression() {
    pcre_free(re);
}

size_t TRegularExpression::GetMatches(const TString &str, TVector<TString> &hits) const {
    int rc;
    unsigned int offset = 0;
    int ovector[100];
    rc = pcre_exec(re, nullptr, str.data(), str.size(), offset, 0, ovector, sizeof(ovector) / sizeof(int));

    hits.clear();
    for(int i = 1; i < rc; ++i) {
        hits.push_back(str.substr(ovector[i * 2], ovector[i * 2 + 1] - ovector[i * 2]));
    }


    return hits.size();
}

void EscapePireRegexChar(wchar16 ch, TUtf16String &result) {
    if (ch >= 0xF000) {
        ch &= 0xFFF;
    }

    switch(ch) {
        case '\0':
            break;

        case '|':   //controls
        case '(':
        case ')':
        case '.':
        case '*':
        case '+':
        case '?':
        case '^':
        case '$':
        case '\\':

        case '&':

        case '{':   //repetition count
        case '}':

        case '[':
        case ']':

        case '~':   //invert
            result.append(1, '\\');
        default:
            result.append(1, ch);
    }
}

TUtf16String EscapePireRegex(const TUtf16String &s) {
    TUtf16String res;
    res.reserve(s.size());

    for (size_t i = 0; i < s.size(); i++) {
        wchar16 ch = s[i];
        EscapePireRegexChar(ch, res);
    }
    return res;
}

TString EscapePireRegex(const TString &s) {
    TUtf16String regex = UTF8ToWide(s);
    TUtf16String res = EscapePireRegex(regex);
    return WideToUTF8(res);
}

} //namespace NWebmaster
