package com.utopiaindustries.util;


import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class StringUtils {

    /**
     * is null or empty
     */
    public static boolean isNullOrEmpty(String str) {
        return str == null || str.isEmpty();
    }

    public static boolean isNotNullAndNotEmpty(String str) {
        return str != null && !str.isEmpty();
    }

    public static boolean isAnyNotZero(String... args) {
        boolean isAnyNotZero = false;
        for (String str : args) {
            isAnyNotZero = isAnyNotZero || isNullEmptyOrZero(str);
        }
        return isAnyNotZero;
    }

    /**
     * is any string not null or empty
     */
    public static boolean isAnyNotNullOrEmpty(String... strings) {
        boolean isAnyNotNullOrEmpty = false;
        for (String str : strings) {
            isAnyNotNullOrEmpty = isAnyNotNullOrEmpty || (!isNullOrEmpty(str));
        }
        return isAnyNotNullOrEmpty;
    }

    /**
     * are all string null or empty
     */
    public static boolean areAllNullOrEmpty(String... strings) {
        for (String str : strings) {
            if (!isNullOrEmpty(str)) {
                return false;
            }
        }
        return true;
    }

    public static boolean areAllNotNullAndNotEmpty(String... strings) {
        boolean flag = false;
        for (String str : strings) {
            if (isNotNullAndNotEmpty(str)) {
                flag = true;
            } else {
                flag = false;
            }
        }
        return flag;
    }

    /**
     * replace last instance of "toReplace" with "replacement"
     */
    public static String replaceLast(String string, String toReplace, String replacement) {
        int pos = string.lastIndexOf(toReplace);
        if (pos > -1) {
            return string.substring(0, pos)
                    + replacement
                    + string.substring(pos + toReplace.length());
        } else {
            return string;
        }
    }

    /**
     * reverse string
     */
    public static String reverseString(String input) {
        StringBuilder backwards = new StringBuilder();
        for (int i = 0; i < input.length(); i++) {
            backwards.append(input.charAt(input.length() - 1 - i));
        }
        return backwards.toString();
    }

    /**
     * format values for MySQL's MATCH/AGAINST phrase
     */
    public static String formatAgainstPhraseValues(String vals, String operator) {
        // convert to array and prepend "+"
        String[] valArr = vals.split(" ");
        for (int i = 0; i < valArr.length; i++) {
            valArr[i] = operator + valArr[i].trim();
        }
        // join by space and return
        return String.join(" ", valArr);
    }

    /**
     * String to float conversion
     */
    public static float stringToFloat(String string) {
        try {
            return Float.parseFloat(string);
        } catch (Exception ex) {
            return 0.0f;
        }
    }

    /**
     * String to double conversion
     */
    public static double strToDouble(String inStr) {
        try {
            return Double.parseDouble(inStr);
        } catch (Exception ex) {
            return 0;
        }
    }

    /**
     * String to long conversion
     */
    public static long strToLong(String inStr) {
        try {
            return Long.parseLong(inStr);
        } catch (Exception ex) {
            return 0;
        }
    }

    /**
     * Compare strings
     */
    public static boolean compare(String str1, String str2) {
        return str1 != null && str2 != null && str1.equalsIgnoreCase(new String(str2));
    }

    /**
     * make like for sql query
     */
    public static String makeLikeForSql(String text) {
        String likeText = null;
        if (!StringUtils.isNullOrEmpty(text)) {
            likeText = "%" + text + "%";
        }
        return likeText;
    }

    /**
     * make start date time by date string
     */
    public static String makeStartDateTimeByDateString(String startDate) {
        String startDateTime = null;
        if (!StringUtils.isNullOrEmpty(startDate)) {
            startDateTime = startDate + " 00:00:00";
        }
        return startDateTime;
    }

    /**
     * make end date time by date string
     */
    public static String makeEndDateTimeByDateString(String endDate) {
        String endDateTime = null;
        if (!StringUtils.isNullOrEmpty(endDate)) {
            endDateTime = endDate + " 23:59:59";
        }
        return endDateTime;
    }

    /**
     * make type empty string for all and default
     */
    public static String getWeightScaleType(String weightScaleType) {
        if (StringUtils.isNullOrEmpty(weightScaleType)) {
            return "";
        } else if (StringUtils.compare(weightScaleType, "ALL")) {
            return "";
        } else {
            return weightScaleType;
        }
    }

    public static String getVehicleRequestCode(String vehicleRequestCode) {
        if (StringUtils.isNullOrEmpty(vehicleRequestCode)) {
            return "";
        } else {
            return vehicleRequestCode;
        }
    }


    /**
     * make end date time by date string
     */
    public static String replaceAt(String str, int afterCharNo, String charToReplace) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            if (i > 0 && (i % afterCharNo == 0)) {
                sb.append(charToReplace);
            }
            sb.append(str.charAt(i));
        }
        return sb.toString();
    }


    //  92333569974 -> 0333 5699744
    public static String getNumberStartWithZero(String number) {
        if (isNullOrEmpty(number)) {
            return "-";
        }
        StringBuilder numberString = new StringBuilder(number);
        // if number starts with 9
        if (numberString.charAt(0) == '9') {

            numberString.replace(0, 2, "0");

            if (numberString.charAt(1) == '-')
                numberString.deleteCharAt(1);
            if (numberString.charAt(4) == '-')
                numberString.deleteCharAt(4);
        }
        // if number starts with +
        else if (numberString.charAt(0) == '+') {
            numberString.replace(0, 3, "0");
            if (numberString.charAt(1) == '-')
                numberString.deleteCharAt(1);
            if (numberString.charAt(4) == '-')
                numberString.deleteCharAt(4);
        }
        numberString.insert(4, " ");
        return numberString.toString();
    }

    // 0333 5699744 -> 92333569974
    public static String getNumberStartWithNonZero(String number) {
        if (isNullOrEmpty(number)) {
            return "-";
        }
        number = number.split(",")[0];
        number = number.replaceAll("\\s+", "");
        StringBuilder numberString = new StringBuilder(number);
        if (numberString.charAt(0) == '0') {
            numberString.replace(0, 1, "92");
        }
        if (numberString.length() >= 6 && numberString.charAt(5) == '-') {
            numberString.replace(5, 6, "");
        }
        return numberString.toString();
    }

    public static String formatNumber(String number) {
        if (isNullOrEmpty(number)) {
            return "-";
        }
        number = number.replaceAll("\\s+", "");
        number = number.replaceAll("-", "");
        StringBuilder numberString = new StringBuilder(number);
        if (numberString.charAt(0) == '0') {
            numberString.replace(0, 1, "92");
        } else if (numberString.charAt(0) == '+') {
            numberString.replace(0, 1, "");
        }

        return numberString.toString();
    }

    public static String padString(String string, int maxLength) {
        String str = "";
        int numChar = maxLength - string.length();
        if (numChar > 0) {
            for (int i = 0; i < numChar; i++)
                str += " ";
            str += string.toString().toUpperCase(Locale.ROOT);
            return str;
        } else {
            return string.toString().toUpperCase(Locale.ROOT).substring(0, 45);
        }

    }

    /**
     * create code from title
     */
    public static String createCode(String title) {
        return title.trim().toUpperCase().replaceAll("\\s+", "_");
    }

    /**
     * get comma separated items array, without spaces
     */
    public static String[] getArrayFromCommaSeparatedString(String commaSeparatedItems) {
        if (!StringUtils.isNullOrEmpty(commaSeparatedItems)) {
            return commaSeparatedItems.split("\\s*,\\s*");
        }
        return new String[0];
    }

    public static Set<Long> getLongListFromCommaSeparatedString(String commaSeparatedItems) {
        if (!StringUtils.isNullOrEmpty(commaSeparatedItems)) {
            String[] strs = commaSeparatedItems.split("\\s*,\\s*");
            return Arrays.stream(strs).map(Long::parseLong).collect(Collectors.toSet());
        }
        return new HashSet<>();
    }


    /**
     * String array to Long array
     */
    public static Long[] stringArrayToLongArray(String[] strArray) {
        if (strArray != null) {
            Long[] longArray = new Long[strArray.length];
            for (int i = 0; i < strArray.length; i++) {
                longArray[i] = strToLong(strArray[i]);
            }
            return longArray;
        }
        return new Long[0];
    }

    public static String encodeEmail(String email) {
        int length = email.length();
        if (length == 0) {
            return "";
        } else {
            StringBuilder str = new StringBuilder(email);
            int startIndex = 2;
            int endIndex = length - 3;
            for (int start = startIndex; start < endIndex - startIndex - 1; start++) {
                str.insert(start, "*");
                str.deleteCharAt(start + 1);
            }
            return str.toString();
        }

    }

    /**
     * get comma separated string from long list
     */
    public static String getCommaSeparatedString(List<Long> items) {
        StringBuilder stringBuilder = new StringBuilder();
        if (items != null) {
            for (int i = 0; i < items.size(); i++) {
                if (i < items.size() - 1) {
                    stringBuilder.append(items.get(i) + ",");
                } else {
                    stringBuilder.append(items.get(i));
                }
            }
        }
        return stringBuilder.toString();
    }

    /**
     * get comma separated string from long Set
     */
    public static String getCommaSeparatedString(Set<Long> items) {
        if (items != null) {
            return getCommaSeparatedString(new ArrayList<Long>(items));
        }
        return "";
    }

    /*
     * is str is null or 0
     * */
    public static boolean isNullEmptyOrZero(String str) {
        return str == null || str.isEmpty() || Long.parseLong(str) == 0;
    }

    /**
     * get Set from comma separated string
     */
    public static Set<String> getSetFromCommaSeparatedString(String string) {
        String[] array = getArrayFromCommaSeparatedString(string);
        if (array != null) {
            return new HashSet<String>(Arrays.asList(array));
        }
        return new HashSet<>();
    }

    /**
     * String Set to Long Set
     */
    public static Set<Long> getLongSet(Set<String> stringSet) {
        Set<Long> longSet = new HashSet<>();
        if (stringSet != null) {
            for (String string : stringSet) {
                longSet.add(NumberUtils.stringToLong(string));
            }
        }
        return longSet;
    }

    /**
     * replace dashes & spaces
     */
    public static String replaceDashesSpaces(String str) {
        return str.replaceAll("-", "").replaceAll("\\s+", "");
    }

    /**
     * is valid email
     */
    public static boolean isValidEmail(String email) {
        if (isNullOrEmpty(email)) {
            return false;
        }
        Pattern pattern = Pattern.compile("^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$");
        return pattern.matcher(email).matches();
    }

    public static boolean containsIgnoreCase(CharSequence str, CharSequence searchStr) {
        if (str != null && searchStr != null) {
            int len = searchStr.length();
            int max = str.length() - len;

            for (int i = 0; i <= max; ++i) {
                if (regionMatches(str, true, i, searchStr, 0, len)) {
                    return true;
                }
            }
            return false;
        } else {
            return false;
        }
    }

    private static boolean regionMatches(CharSequence cs, boolean ignoreCase, int thisStart, CharSequence substring, int start, int length) {
        if (cs instanceof String && substring instanceof String) {
            return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length);
        } else {
            int index1 = thisStart;
            int index2 = start;
            int tmpLen = length;
            int srcLen = cs.length() - thisStart;
            int otherLen = substring.length() - start;
            if (thisStart >= 0 && start >= 0 && length >= 0) {
                if (srcLen >= length && otherLen >= length) {
                    while (tmpLen-- > 0) {
                        char c1 = cs.charAt(index1++);
                        char c2 = substring.charAt(index2++);
                        if (c1 != c2) {
                            if (!ignoreCase) {
                                return false;
                            }

                            if (Character.toUpperCase(c1) != Character.toUpperCase(c2) && Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
                                return false;
                            }
                        }
                    }
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
    }

    public static String getOrdinal(int number) {
        if (number <= 0) {
            throw new IllegalArgumentException("Number must be greater than zero");
        }
        int mod100 = number % 100;
        int mod10 = number % 10;

        if (mod100 >= 11 && mod100 <= 13) {
            return number + "th";
        }
        switch (mod10) {
            case 1:
                return number + "st";
            case 2:
                return number + "nd";
            case 3:
                return number + "rd";
            default:
                return number + "th";
        }
    }

    /*
     *  check str contains all numbers
     * */
    public static boolean isValidCellNumber(String str) {
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i)) && str.charAt(i) != '-') {
                return false;
            }
        }
        return true;
    }

    /*
     *  remove trailing zeros from string
     * */
    public static String removeTrailingZeros(String merchantId) {
        if (!isNullOrEmpty(merchantId)) {
            return merchantId.replaceFirst("^0+(?!$)", "");
        }
        return merchantId;
    }
}