// © 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_SIGN) {
}

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 */
