/* UtilLib - Copyright (c) 2018 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.mapeadores.util.text;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;


/**
 *
 * @author Vincent Calame
 */
public final class StringCheckerUtils {

    public final static StringChecker URL = new UrlChecker();

    private StringCheckerUtils() {

    }

    public static StringChecker newLengthChecker(int min, int max) {
        if (min < 0) {
            min = 0;
        }
        if (max < min) {
            max = min;
        }
        return new LengthChecker(min, max);
    }


    private static class UrlChecker implements StringChecker {

        private UrlChecker() {

        }

        @Override
        public String check(String href) {
            if (href == null) {
                return null;
            }
            href = href.trim();
            if (href.length() == 0) {
                return null;
            }
            if (href.startsWith("www.")) {
                href = "http://" + href;
            }
            href = href.replace(" ", "%20");
            try {
                URI uri = new URI(href);
                if (uri.isAbsolute()) {
                    new URL(uri.toString());
                    return uri.toASCIIString();
                } else {
                    new URL("http://" + uri.toString());
                    return "http://" + uri.toASCIIString();
                }
            } catch (URISyntaxException | MalformedURLException e) {
                return null;
            }
        }


    }


    private static class LengthChecker implements StringChecker {

        private final int min;
        private final int max;

        private LengthChecker(int min, int max) {
            this.min = min;
            this.max = max;
        }

        @Override
        public String check(String value) {
            if (value == null) {
                return null;
            }
            int length = value.length();
            if (length <= max) {
                return value;
            }
            boolean done = false;
            int endIndex = 0;
            for (int i = max; i > min; i--) {
                char carac = value.charAt(i);
                switch (carac) {
                    case '?':
                    case '!':
                    case '.':
                    case '…':
                        endIndex = i;
                        done = true;
                        break;
                }
                if (done) {
                    break;
                }
            }
            if (done) {
                endIndex = testNearEndIndex(endIndex, value);
                return value.substring(0, endIndex + 1);
            } else {
                int stop = checkStop(value);
                return value.substring(0, stop) + '…';
            }
        }

        private int checkStop(String value) {
            for (int i = max; i > min; i--) {
                if (value.charAt(i) == ' ') {
                    return i;
                }
            }
            return min;
        }

        private int testNearEndIndex(int endIndex, String value) {
            int length = value.length();
            int added = 0;
            for (int i = (endIndex + 1); i < length; i++) {
                char carac = value.charAt(i);
                switch (carac) {
                    case '.':
                        added++;
                        if (added > 2) {
                            return endIndex + added;
                        }
                        break;
                    case ')':
                    case ']':
                        added++;
                        return endIndex + added;
                    default:
                        return endIndex + added;
                }
            }
            return endIndex + added;
        }

    }

}
