package io.github.benas.unixstream;

import java.util.Objects;
import java.util.function.Function;

/**
 * This class consists of {@code static} factory methods to create commons functions.
 *
 * @author Mahmoud Ben Hassine (mahmoud@benhassine.fr)
 */
public class Functions {

    /**
     * Compact a string by removing all white spaces.
     *
     * @return a compact string
     */
    public static Function<String, String> compact() {
        return s -> s.replaceAll("\\s", "");
    }

    /**
     * Split a String by a delimiter and extract fields
     *
     * @param delimiter the delimiter
     * @param field     the index of the field to extract (starting from 1).
     * @return a cut function
     */
    public static Function<String, String> cut(final String delimiter, final int field) {
        Objects.requireNonNull(delimiter, "The delimiter must not be null");
        if (field < 1) {
            throw new IllegalArgumentException("Field must be >= 1");
        }
        return s -> {
            String[] strings = s.split(delimiter);
            return field <= strings.length ? strings[field - 1] : "";
        };
    }

    /**
     * Replace Windows line separators (CRLF) by Unix line separators (LF).
     *
     * @return a dos2unix function
     */
    public static Function<String, String> dos2unix() {
        return s -> s.replaceAll("\r\n", "\n"); // or s.replaceAll("\r", "");
    }

    /**
     * Replace tabs with white spaces in a String.
     *
     * @return a expand function
     */
    public static Function<String, String> expand() {
        return s -> s.replaceAll("\t", " ");
    }

    /**
     * Replace white spaces with tabs in a String.
     *
     * @return a unexpand function
     */
    public static Function<String, String> unexpand() {
        return s -> s.replaceAll(" ", "\t");
    }

    /**
     * Fold a String with a given width.
     *
     * @param width         the fold width
     * @param lineSeparator the line separator
     * @return a fold function
     */
    public static Function<String, String> fold(final int width, final String lineSeparator) {
        Objects.requireNonNull(lineSeparator, "The line separator must not be null");
        if (width < 1) {
            throw new IllegalArgumentException("Width must be >= 1");
        }
        return s -> {
            StringBuilder stringBuilder = new StringBuilder();
            int i = 0;
            int length = s.length();
            while (i < length && !String.valueOf(s.charAt(i)).equals(lineSeparator)) {
                stringBuilder.append(s.charAt(i));
                if (++i % width == 0) {
                    stringBuilder.append(lineSeparator);
                }
            }
            return stringBuilder.toString();
        };
    }

    /**
     * Transform a String to lower case.
     *
     * @return a lowercase function
     */
    public static Function<String, String> lowercase() {
        return String::toLowerCase;
    }

    /**
     * Transform a String to upper case.
     *
     * @return a uppercase function
     */
    public static Function<String, String> uppercase() {
        return String::toUpperCase;
    }

    /**
     * Transform an Object to a String by calling {@link Object#toString()}.
     *
     * @param <T> the type of objects in the stream
     * @return a stringify function
     */
    public static <T> Function<T, String> str() {
        return Object::toString;
    }

    /**
     * Replace patterns with expressions in a stream of Strings.
     *
     * @param regexp      the regexp to look for
     * @param replacement the replacement to apply
     * @return a translate function
     */
    public static Function<String, String> tr(final String regexp, final String replacement) {
        Objects.requireNonNull(regexp, "The regular expression must not be null");
        Objects.requireNonNull(replacement, "The replacement must not be null");
        return s -> s.replaceAll(regexp, replacement);
    }

    /**
     * Trim a String by removing trailing white spaces.
     *
     * @return a trim function
     */
    public static Function<String, String> trim() {
        return String::trim;
    }

    /**
     * Truncate a String to a limited size.
     *
     * @param size the new String size
     * @return a trunc function
     */
    public static Function<String, String> trunc(final int size) {
        if (size < 1) {
            throw new IllegalArgumentException("Size must be >= 1");
        }
        return s -> s.substring(0, size);
    }

}

@@ -30,16 +30,68 @@
 tream;%0A%0A
+import io.github.benas.unixstream.components.Fold;%0A%0A
 import j
@@ -2839,32 +2839,363 @@
       %7D;%0A    %7D%0A%0A
+    /**%0A     * Fold a String with a given width.%0A     * Lines will be separated with the default System line separator%0A     *%0A     * @param width         the fold width%0A     * @return a fold function%0A     */%0A    public static Function%3CString, String%3E fold(final int width) %7B%0A        return fold(width, Fold.LINE_SEPARATOR);%0A    %7D%0A%0A
     /**%0A     * T

add fold method with default line separator