package com.atlassian.bitbucket.util;

import com.google.common.base.Joiner;

import java.util.Arrays;
import java.util.List;

import static com.google.common.base.Preconditions.checkArgument;

public class TextUtils {

    private TextUtils() {
        throw new UnsupportedOperationException(getClass().getName() +
                " is a utility class and should not be instantiated");
    }

    public static String pluralise(String word, long n) {
        return pluralise(word, word + 's', n);
    }

    public static String pluralise(String singular, String plural, long n) {
        checkArgument(n >= 0);
        return n > 1 ? plural : singular;
    }

    /**
     * Truncates a file path of the form "a/b/c" to a maximum of {len} characters,
     * while keeping at least the first {startSegments} and last {endSegments}.
     * </p>
     * NOTE: The segment rules take precedence over the max length.
     * </p>
     * For example the path "foo/bar/baz/Test.java" when truncated to the first 1
     * and last 2 segments, with a max length of 10 characters will equal:
     * "foo/.../baz/Test.java"
     *
     * @param path the file path to be truncated - assumption is separators are '/'
     * @param startSegments the number of initial segments to always keep
     * @param endSegments the number of end segments to always keep (inclusive of the last segment)
     * @param len the maximum number of characters to try and keep the path within
     * @return the truncated path
     */
    public static String truncatePath(String path, int startSegments, int endSegments, int len) {
        checkArgument(len > 0, "len must be positive");
        checkArgument(startSegments >= 0, "startSegments must be zero or more");
        checkArgument(endSegments >= 0, "endSegments must be zero or more");

        int pathLength = path.length();

        if (pathLength <= len) {
            return path;
        }

        List<String> segments = Arrays.asList(path.split("/", 0));

        if (startSegments + endSegments >= segments.size()) {
            return path;
        }

        boolean trailingSlash = path.endsWith("/");

        for (int index = startSegments, endIndex = segments.size() - endSegments; index < endIndex; index++) {
            String oldValue;
            if (index == startSegments) {
                oldValue = segments.set(index, "...");
                pathLength -= oldValue.length() - 3; // we replaced the path with 3 characters
            } else {
                oldValue = segments.set(index, null);
                pathLength -= (oldValue.length() + 1); // + 1 for trailing slash
            }

            if (pathLength <= len) {
                break;
            }
        }

        StringBuilder pathBuilder = new StringBuilder(pathLength);
        pathBuilder = Joiner.on('/').skipNulls().appendTo(pathBuilder, segments);

        if (trailingSlash) {
            pathBuilder.append('/');
        }

        if (pathBuilder.length() > path.length()) { // you had ONE JOB truncatePath!
            return path;
        } else {
            return pathBuilder.toString();
        }
    }
}
