package io.domisum.lib.auxiliumlib.util;

import io.domisum.lib.auxiliumlib.PHR;
import io.domisum.lib.auxiliumlib.annotations.API;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@API
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class StringListUtil
{
	
	private static final String DEFAULT_DELIMITER = ", ";
	
	
	@API
	public static <T> String list(Iterable<T> iterable, Function<T, Object> function, String delimiter)
	{
		var display = new StringBuilder();
		boolean removeDelimiter = false;
		for(T element : iterable)
		{
			var elementDisplay = function == null ? element : function.apply(element);
			display.append(elementDisplay);
			display.append(delimiter);
			removeDelimiter = true;
		}
		
		if(removeDelimiter)
			display.delete(display.length()-delimiter.length(), display.length());
		
		return display.toString();
	}
	
	@API
	public static <T> String list(Iterable<T> iterable, Function<T, Object> function)
	{
		return list(iterable, function, DEFAULT_DELIMITER);
	}
	
	@API
	public static String list(Iterable<?> iterable, String delimiter)
	{
		return list(iterable, null, delimiter);
	}
	
	@API
	public static String list(Iterable<?> iterable)
	{
		return list(iterable, DEFAULT_DELIMITER);
	}
	
	@API
	public static String list(String delimiter, Object... items)
	{
		return list(Arrays.asList(items), delimiter);
	}
	
	
	@API
	public static <T> String list(Map<?, T> map, String delimiter, Function<T, Object> valueFunction)
	{
		var mappings = new ArrayList<String>();
		for(var entry : map.entrySet())
		{
			String mapping = PHR.r("'{}'->'{}'", entry.getKey(), valueFunction.apply(entry.getValue()));
			mappings.add(mapping);
		}
		mappings.sort(Comparator.naturalOrder());
		
		return list(mappings, delimiter);
	}
	
	@API
	public static <T> String list(Map<?, T> map, Function<T, Object> valueFunction)
	{
		return list(map, DEFAULT_DELIMITER, valueFunction);
	}
	
	
	@API
	public static String list(Map<?, ?> map, String delimiter)
	{
		return list(map, delimiter, v->v);
	}
	
	@API
	public static String list(Map<?, ?> map)
	{
		return list(map, DEFAULT_DELIMITER);
	}
	
	
	@API
	public static String list(Stream<?> stream, String delimiter)
	{
		var elementsCollection = stream.collect(Collectors.toList());
		return list(elementsCollection, delimiter);
	}
	
	@API
	public static String list(Stream<?> stream)
	{
		return list(stream, DEFAULT_DELIMITER);
	}
	
	
	@API
	public static <T> String listInSingleQuotes(Iterable<T> iterable)
	{
		return list(iterable, s->"'"+s+"'");
	}
	
	@API
	public static <T> String listInDoubleQuotes(Iterable<T> iterable)
	{
		return list(iterable, s->"\""+s+"\"");
	}
	
}

@@ -290,16 +290,42 @@
 il.Map;%0A
+import java.util.Objects;%0A
 import j
@@ -1617,33 +1617,36 @@
 %09public static %3C
-T
+K, V
 %3E String list(Ma
@@ -1643,28 +1643,28 @@
 ng list(Map%3C
-?, T
+K, V
 %3E map, Strin
@@ -1675,17 +1675,19 @@
 limiter,
- 
+%0A%09%09
 Function
@@ -1683,33 +1683,56 @@
 %0A%09%09Function%3C
-T, Object
+K, ?%3E keyFunction, Function%3CV, ?
 %3E valueFunct
@@ -1850,21 +1850,35 @@
 .r(%22
-'
 %7B%7D
-'
 -%3E
-'
 %7B%7D
-'
 %22, 
+keyFunction.apply(
 entr
@@ -1887,16 +1887,17 @@
 getKey()
+)
 , valueF
@@ -2112,22 +2112,17 @@
 tion%3CT, 
-Object
+?
 %3E valueF
@@ -2175,134 +2175,62 @@
 ER, 
-valueFunction);%0A%09%7D%0A%09%0A%09%0A%09@API%0A%09public static String list(Map%3C?, ?%3E map, String delimiter)%0A%09%7B%0A%09%09return list(map, delimiter, v-%3Ev
+StringListUtil::defaultMapEntryFunction, valueFunction
 );%0A%09
@@ -2312,32 +2312,114 @@
 EFAULT_DELIMITER
+, StringListUtil::defaultMapEntryFunction, StringListUtil::defaultMapEntryFunction
 );%0A%09%7D%0A%09%0A%09%0A%09@API%0A
@@ -2944,10 +2944,165 @@
 );%0A%09%7D%0A%09%0A
+%09%0A%09// UTIL%0A%09private static %3CT%3E Object defaultMapEntryFunction(T t)%0A%09%7B%0A%09%09if(t instanceof String)%0A%09%09%09return %22'%22+t+%22'%22;%0A%09%09%0A%09%09return Objects.toString(t);%0A%09%7D%0A%09%0A
 %7D%0A

Remove default quotes in map methods in StringListUtil