package org.atea.nlptools.macroniser.util;

import static java.lang.Character.isLowerCase;
import static java.lang.Character.toLowerCase;
import static java.lang.Character.toUpperCase;

public class StringUtil
{
    public static boolean containsAccents(String str)
    {
        if (str == null) {
            return false;
        }

        for (char c : str.toCharArray())
        {
            if (isAccented(c)) {
                return true;
            }
        }

        return false;
    }

    public static String removeAccents(String str)
    {
        if (str == null || !containsAccents(str)) {
            return str;
        }

        final StringBuilder buffer = new StringBuilder(str.length());
        for (char c : str.toCharArray()) {
            buffer.append(removeAccent(c));
        }

        return buffer.toString();
    }

    public static String toDoubleVowel(String str)
    {
        if (str == null || !containsAccents(str)) {
            return str;
        }

        final StringBuilder buffer = new StringBuilder();
        for (char c : str.toCharArray()) {
            buffer.append(toDoubleVowel(c));
        }

        return buffer.toString();
    }

    public static String copyCapitalization(String source, String destination)
        throws IllegalArgumentException
    {
        checkNotNull(source);
        checkNotNull(destination);
        checkEqualLength(source, destination);

        final StringBuilder buffer = new StringBuilder(source.length());
        for (int i = 0; i < source.length(); i++)
        {
            buffer.append(
                isLowerCase(source.charAt(i))
                    ? toLowerCase(destination.charAt(i))
                    : toUpperCase(destination.charAt(i))
            );
        }
        
        return buffer.toString();
    }

    public static String copyDVowelCapitalization(String dvowel, String destination)
    {
        checkNotNull(dvowel);
        checkNotNull(destination);

        final StringBuilder buffer = new StringBuilder(dvowel.length());
        for (int i = 0, j = 0; i < destination.length(); i++, j++)
        {
            buffer.append(
                isLowerCase(dvowel.charAt(j))
                    ? toLowerCase(destination.charAt(i))
                    : toUpperCase(destination.charAt(i))
            );
                
            if (isAccented(destination.charAt(i))) {
                j++;
            }
        }
        
        return buffer.toString();
    }

    public static Boolean isNullOrWhiteSpace(String value)
    {
        if (value == null) {
            return true;
        }

        Boolean result = true;

        for (int i = 0; i < value.length(); i++)
        {
            switch (value.charAt(i)) {
                case ' ':
                case '\r':
                case '\n':
                case '\t':
                    result = true;
                    break;
                default:
                    return false;
            }
        }
        
        return result;
    }

    private static void checkNotNull(String str)
        throws IllegalArgumentException
    {
        if (str == null) {
            throw new IllegalArgumentException("Required a non null String, found null String.");
        }
    }

    private static void checkEqualLength(String s1, String s2)
        throws IllegalArgumentException
    {
        if (s1.length() != s2.length()) {
            throw new IllegalArgumentException("Required equal String lengths, found unequal String lengths: s1=" + s1.length() + ", s2=" + s2.length());
        }
    }

    public static boolean isAccented(char c)
    {
        switch (c)
        {
            //Set A
            case 'ā':
                return true;
            case 'ē':
                return true;
            case 'ī':
                return true;
            case 'ō':
                return true;
            case 'ū':
                return true;
            case 'Ā':
                return true;
            case 'Ē':
                return true;
            case 'Ī':
                return true;
            case 'Ō':
                return true;
            case 'Ū':
                return true;
            //Set B
            case 'ä':
                return true;
            case 'ë':
                return true;
            case 'ï':
                return true;
            case 'ö':
                return true;
            case 'ü':
                return true;
            case 'Ä':
                return true;
            case 'Ë':
                return true;
            case 'Ï':
                return true;
            case 'Ö':
                return true;
            case 'Ü':
                return true;
            //Set C
            case 'à':
                return true;
            case 'è':
                return true;
            case 'ì':
                return true;
            case 'ò':
                return true;
            case 'ù':
                return true;
            case 'À':
                return true;
            case 'È':
                return true;
            case 'Ì':
                return true;
            case 'Ò':
                return true;
            case 'Ù':
                return true;
            //Set D
            default:
                return false;
        }
    }

    public static char removeAccent(char c)
    {
        switch (c)
        {
            //Set A
            case 'ā':
                return 'a';
            case 'ē':
                return 'e';
            case 'ī':
                return 'i';
            case 'ō':
                return 'o';
            case 'ū':
                return 'u';
            case 'Ā':
                return 'A';
            case 'Ē':
                return 'E';
            case 'Ī':
                return 'I';
            case 'Ō':
                return 'O';
            case 'Ū':
                return 'U';
            //Set B
            case 'ä':
                return 'a';
            case 'ë':
                return 'e';
            case 'ï':
                return 'i';
            case 'ö':
                return 'o';
            case 'ü':
                return 'u';
            case 'Ä':
                return 'A';
            case 'Ë':
                return 'E';
            case 'Ï':
                return 'I';
            case 'Ö':
                return 'O';
            case 'Ü':
                return 'U';
            //Set C
            case 'à':
                return 'a';
            case 'è':
                return 'e';
            case 'ì':
                return 'i';
            case 'ò':
                return 'o';
            case 'ù':
                return 'u';
            case 'À':
                return 'A';
            case 'È':
                return 'E';
            case 'Ì':
                return 'I';
            case 'Ò':
                return 'O';
            case 'Ù':
                return 'U';
            //Set D
            default:
                return c;
        }
    }

    public static String toDoubleVowel(char c)
    {
        switch (c)
        {
            //Set A
            case 'ā':
                return "aa";
            case 'ē':
                return "ee";
            case 'ī':
                return "ii";
            case 'ō':
                return "oo";
            case 'ū':
                return "uu";
            case 'Ā':
                return "Aa";
            case 'Ē':
                return "Ee";
            case 'Ī':
                return "Ii";
            case 'Ō':
                return "Oo";
            case 'Ū':
                return "Uu";
            //Set B
            case 'ä':
                return "aa";
            case 'ë':
                return "ee";
            case 'ï':
                return "ii";
            case 'ö':
                return "oo";
            case 'ü':
                return "uu";
            case 'Ä':
                return "Aa";
            case 'Ë':
                return "Ee";
            case 'Ï':
                return "Ii";
            case 'Ö':
                return "Oo";
            case 'Ü':
                return "Uu";
            //Set C
            case 'à':
                return "aa";
            case 'è':
                return "ee";
            case 'ì':
                return "ii";
            case 'ò':
                return "oo";
            case 'ù':
                return "uu";
            case 'À':
                return "Aa";
            case 'È':
                return "Ee";
            case 'Ì':
                return "Ii";
            case 'Ò':
                return "Oo";
            case 'Ù':
                return "Uu";
            //Set D
            default:
                return Character.toString(c);
        }
    }
}
