/*
 * @Copyright 2018-2026 HardBackNutter
 * @License GNU General Public License
 *
 * This file is part of NeverTooManyBooks.
 *
 * NeverTooManyBooks is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * NeverTooManyBooks is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with NeverTooManyBooks. If not, see <http://www.gnu.org/licenses/>.
 */

package com.hardbacknutter.nevertoomanybooks.core.utils.textnormaliser;

import androidx.annotation.NonNull;

import java.text.Normalizer;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * Adding the full com.ibm icu would make a Transliterator usable with api 26+,
 * but would add 10Mb to the app size. Granted we could tweak this but given
 * the plan is to drop support for Android 8/9/10 eventually... no point.
 * <p>
 * Replacement map and docs generated by ChatGPT.
 * <p>
 * | Locale                 | Status      | Notes                                   |
 * | ---------------------- | ----------- | --------------------------------------- |
 * | `cs`, `sk`             | ✅          | č, ě, š, ž, ľ handled by NFD            |
 * | `de`                   | ✅          | ß manually replaced                     |
 * | `el`                   | ⚠️ partial  | Greek not transliterated (can be added) |
 * | `en`, `en_GB`          | ✅          | ASCII                                   |
 * | `es`, `fr`, `pt`, `it` | ✅          | Accents handled via NFD                 |
 * | `gl`, `pl`, `hu`       | ✅          | Special letters handled (ł, đ, etc.)    |
 * | `nl`                   | ✅          | Mostly ASCII                            |
 * | `ru`                   | ⚠️ partial  | Cyrillic not transliterated             |
 * | `sv`, `tr`, `vi`       | ✅          | å, ö, ü, đ, ı, İ handled                |
 * | `zh_CN`, `zh_TW`       | ⚠️ no       | Requires separate Pinyin transliterator |
 * | `ta`                   | ⚠️ minimal  | Very basic replacements only            |
 *
 * @noinspection CheckStyle
 */
class TransliteratorApi26
        implements TextTransliterator {

    /** Remove Unicode combining marks (accents, diacritics). */
    private static final Pattern DIACRITICS_PATTERN = Pattern.compile("\\p{M}");

    /** Manual replacements for characters that don’t decompose into ASCII. */
    private static final Map<Character, String> EXTRA_REPLACEMENTS = new HashMap<>();

    static {
        // German (de)
        EXTRA_REPLACEMENTS.put('ß', "ss");

        // Polish, Czech, Slovak, etc. (pl, cs, sk)
        EXTRA_REPLACEMENTS.put('ł', "l");
        EXTRA_REPLACEMENTS.put('Ł', "L");
        EXTRA_REPLACEMENTS.put('đ', "d");
        EXTRA_REPLACEMENTS.put('Đ', "D");
        EXTRA_REPLACEMENTS.put('ø', "o");
        EXTRA_REPLACEMENTS.put('Ø', "O");

        // Ligatures (used in fr, da, is, etc.)
        EXTRA_REPLACEMENTS.put('æ', "ae");
        EXTRA_REPLACEMENTS.put('Æ', "Ae");
        EXTRA_REPLACEMENTS.put('œ', "oe");
        EXTRA_REPLACEMENTS.put('Œ', "Oe");

        // Icelandic, Old English
        EXTRA_REPLACEMENTS.put('þ', "th");
        EXTRA_REPLACEMENTS.put('Þ', "Th");
        EXTRA_REPLACEMENTS.put('ð', "d");
        EXTRA_REPLACEMENTS.put('Ð', "D");

        // Turkish (tr)
        EXTRA_REPLACEMENTS.put('ı', "i");
        EXTRA_REPLACEMENTS.put('İ', "I");

        // Vietnamese (vi) -> these two already added above
        // EXTRA_REPLACEMENTS.put('đ', "d");
        // EXTRA_REPLACEMENTS.put('Đ', "D");

        // Scandinavian (sv, no, da)
        EXTRA_REPLACEMENTS.put('å', "a");
        EXTRA_REPLACEMENTS.put('Å', "A");
        EXTRA_REPLACEMENTS.put('ä', "a");
        EXTRA_REPLACEMENTS.put('Ä', "A");
        EXTRA_REPLACEMENTS.put('ö', "o");
        EXTRA_REPLACEMENTS.put('Ö', "O");

        // French, Spanish, Portuguese, Italian, etc. usually covered by NFD
        // No need to map é → e, ü → u, etc. — they decompose properly

        // Tamil (ta), Chinese (zh), Russian (ru), Greek (el) → typically outside ASCII
        // No general transliteration here — keep or handle separately if needed
    }

    @Override
    @NonNull
    public String transliterate(@NonNull final CharSequence text) {
        // Decompose accents (NFD)
        String normalised = Normalizer.normalize(text, Normalizer.Form.NFD);
        // Remove combining diacritics (accents)
        normalised = DIACRITICS_PATTERN.matcher(normalised).replaceAll("");
        // Replace extra characters that don't decompose
        final StringBuilder result = new StringBuilder(normalised.length());
        for (int i = 0; i < normalised.length(); i++) {
            final char c = normalised.charAt(i);
            final String replacement = EXTRA_REPLACEMENTS.get(c);
            result.append(replacement != null ? replacement : c);
        }
        return result.toString();
    }
}

