// © 2018 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

// Allow implicit conversion from char16_t* to UnicodeString for this file:
// Helpful in toString methods and elsewhere.
#define UNISTR_FROM_STRING_EXPLICIT

#include "numparse_types.h"
#include "numparse_symbols.h"
#include "numparse_utils.h"

using namespace icu;
using namespace icu::numparse;
using namespace icu::numparse::impl;


SymbolMatcher::SymbolMatcher(const UnicodeString& symbolString, unisets::Key key) {
    fUniSet = unisets::get(key);
    if (fUniSet->contains(symbolString)) {
        fString.setToBogus();
    } else {
        fString = symbolString;
    }
}

const UnicodeSet* SymbolMatcher::getSet() const {
    return fUniSet;
}

bool SymbolMatcher::match(StringSegment& segment, ParsedNumber& result, UErrorCode&) const {
    // Smoke test first; this matcher might be disabled.
    if (isDisabled(result)) {
        return false;
    }

    // Test the string first in order to consume trailing chars greedily.
    int overlap = 0;
    if (!fString.isEmpty()) {
        overlap = segment.getCommonPrefixLength(fString);
        if (overlap == fString.length()) {
            segment.adjustOffset(fString.length());
            accept(segment, result);
            return false;
        }
    }

    int cp = segment.getCodePoint();
    if (cp != -1 && fUniSet->contains(cp)) {
        segment.adjustOffset(U16_LENGTH(cp));
        accept(segment, result);
        return false;
    }

    return overlap == segment.length();
}

bool SymbolMatcher::smokeTest(const StringSegment& segment) const {
    return segment.startsWith(*fUniSet) || segment.startsWith(fString);
}

UnicodeString SymbolMatcher::toString() const {
    // TODO: Customize output for each symbol
    return u"<Symbol>";
}


IgnorablesMatcher::IgnorablesMatcher(unisets::Key key)
        : SymbolMatcher({}, key) {
}

bool IgnorablesMatcher::isFlexible() const {
    return true;
}

UnicodeString IgnorablesMatcher::toString() const {
    return u"<Ignorables>";
}

bool IgnorablesMatcher::isDisabled(const ParsedNumber&) const {
    return false;
}

void IgnorablesMatcher::accept(StringSegment&, ParsedNumber&) const {
    // No-op
}


InfinityMatcher::InfinityMatcher(const DecimalFormatSymbols& dfs)
        : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kInfinitySymbol), unisets::INFINITY_KEY) {
}

bool InfinityMatcher::isDisabled(const ParsedNumber& result) const {
    return 0 != (result.flags & FLAG_INFINITY);
}

void InfinityMatcher::accept(StringSegment& segment, ParsedNumber& result) const {
    result.flags |= FLAG_INFINITY;
    result.setCharsConsumed(segment);
}


MinusSignMatcher::MinusSignMatcher(const DecimalFormatSymbols& dfs, bool allowTrailing)
        : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol), unisets::MINUS_SIGN),
          fAllowTrailing(allowTrailing) {
}

bool MinusSignMatcher::isDisabled(const ParsedNumber& result) const {
    return !fAllowTrailing && result.seenNumber();
}

void MinusSignMatcher::accept(StringSegment& segment, ParsedNumber& result) const {
    result.flags |= FLAG_NEGATIVE;
    result.setCharsConsumed(segment);
}


NanMatcher::NanMatcher(const DecimalFormatSymbols& dfs)
        : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kNaNSymbol), unisets::EMPTY) {
}

bool NanMatcher::isDisabled(const ParsedNumber& result) const {
    return result.seenNumber();
}

void NanMatcher::accept(StringSegment& segment, ParsedNumber& result) const {
    result.flags |= FLAG_NAN;
    result.setCharsConsumed(segment);
}


PaddingMatcher::PaddingMatcher(const UnicodeString& padString)
        : SymbolMatcher(padString, unisets::EMPTY) {}

bool PaddingMatcher::isFlexible() const {
    return true;
}

bool PaddingMatcher::isDisabled(const ParsedNumber&) const {
    return false;
}

void PaddingMatcher::accept(StringSegment&, ParsedNumber&) const {
    // No-op
}


PercentMatcher::PercentMatcher(const DecimalFormatSymbols& dfs)
        : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kPercentSymbol), unisets::PERCENT_SIGN) {
}

bool PercentMatcher::isDisabled(const ParsedNumber& result) const {
    return 0 != (result.flags & FLAG_PERCENT);
}

void PercentMatcher::accept(StringSegment& segment, ParsedNumber& result) const {
    result.flags |= FLAG_PERCENT;
    result.setCharsConsumed(segment);
}


PermilleMatcher::PermilleMatcher(const DecimalFormatSymbols& dfs)
        : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kPerMillSymbol), unisets::PERMILLE_SIGN) {
}

bool PermilleMatcher::isDisabled(const ParsedNumber& result) const {
    return 0 != (result.flags & FLAG_PERMILLE);
}

void PermilleMatcher::accept(StringSegment& segment, ParsedNumber& result) const {
    result.flags |= FLAG_PERMILLE;
    result.setCharsConsumed(segment);
}


PlusSignMatcher::PlusSignMatcher(const DecimalFormatSymbols& dfs, bool allowTrailing)
        : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol), unisets::PLUS_SIGN),
          fAllowTrailing(allowTrailing) {
}

bool PlusSignMatcher::isDisabled(const ParsedNumber& result) const {
    return !fAllowTrailing && result.seenNumber();
}

void PlusSignMatcher::accept(StringSegment& segment, ParsedNumber& result) const {
    result.setCharsConsumed(segment);
}


#endif /* #if !UCONFIG_NO_FORMATTING */
