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.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

@API
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class StringListUtil
{
	
	private static final String DEFAULT_DELIMITER = ", ";
	
	
	// HORIZONTALLY
	@API
	public static <T> String listHorizontally(List<T> list, Function<T, Object> function, String delimiter)
	{
		var combined = new StringBuilder();
		for(int i = 0; i < list.size(); i++)
		{
			var element = list.get(i);
			var elementDisplay = function == null ? element : function.apply(element);
			combined.append(elementDisplay);
			
			boolean isLastElement = (i+1) == list.size();
			combined.append(isLastElement ? "" : delimiter);
		}
		
		return combined.toString();
	}
	
	@API
	public static <T> String listHorizontally(List<T> list, Function<T, Object> function)
	{
		return listHorizontally(list, function, DEFAULT_DELIMITER);
	}
	
	@API
	public static String listHorizontally(List<?> list)
	{
		return listHorizontally(list, DEFAULT_DELIMITER);
	}
	
	@API
	public static String listHorizontally(List<?> list, String delimiter)
	{
		return listHorizontally(list, null, delimiter);
	}
	
	
	@API
	public static String listHorizontally(Collection<?> collection, String delimiter)
	{
		return listHorizontally(new ArrayList<>(collection), delimiter);
	}
	
	@API
	public static String listHorizontally(Collection<?> collection)
	{
		return listHorizontally(collection, DEFAULT_DELIMITER);
	}
	
	
	@API
	public static <T> String listHorizontally(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 listHorizontally(mappings, delimiter);
	}
	
	@API
	public static <T> String listHorizontally(Map<?, T> map, Function<T, Object> valueFunction)
	{
		return listHorizontally(map, DEFAULT_DELIMITER, valueFunction);
	}
	
	
	@API
	public static String listHorizontally(Map<?, ?> map, String delimiter)
	{
		return listHorizontally(map, delimiter, v->v);
	}
	
	@API
	public static String listHorizontally(Map<?, ?> map)
	{
		return listHorizontally(map, DEFAULT_DELIMITER);
	}
	
	
	// VERTICALLY
	@API
	public static String listVertically(List<?> list)
	{
		var itemDisplays = new ArrayList<String>();
		for(var item : list)
			itemDisplays.add(PHR.r(" - {}", item.toString()));
		
		return listHorizontally(itemDisplays, "\n");
	}
	
	@API
	public static String listVertically(Collection<?> collection)
	{
		return listVertically(new ArrayList<>(collection));
	}
	
	@API
	public static String listVertically(Map<?, ?> map)
	{
		var entryStrings = new ArrayList<String>();
		for(var entry : map.entrySet())
		{
			String entryString = "'"+entry.getKey()+"' -> '"+entry.getValue()+"'";
			entryStrings.add(entryString);
		}
		
		Collections.sort(entryStrings);
		return listVertically(entryStrings);
	}
	
}

@@ -597,36 +597,44 @@
 orizontally(
-List%3CT%3E list
+Iterable%3CT%3E iterable
 , Function%3CT
@@ -680,24 +680,23 @@
 %7B%0A%09%09var 
-combined
+display
  = new S
@@ -717,78 +717,72 @@
 ;%0A%09%09
-for(int i = 0; i %3C list.size(); i++)%0A%09%09%7B%0A%09%09%09var element = list.get(i);
+boolean removeDelimiter = false;%0A%09%09for(T element : iterable)%0A%09%09%7B
 %0A%09%09%09
@@ -855,32 +855,31 @@
 lement);%0A%09%09%09
-combined
+display
 .append(elem
@@ -898,114 +898,165 @@
 %0A%09%09%09
-%0A%09%09%09boolean isLastElement = (i+1) == list.size();%0A%09%09%09combined.append(isLastElement ? %22%22 : delimiter
+display.append(delimiter);%0A%09%09%09removeDelimiter = true;%0A%09%09%7D%0A%09%09%0A%09%09if(removeDelimiter)%0A%09%09%09display.delete(display.length()-delimiter.length(), display.length()
 );%0A
-%09%09%7D%0A
 %09%09%0A%09
@@ -1067,16 +1067,15 @@
 urn 
-combined
+display
 .toS
@@ -1141,20 +1141,28 @@
 lly(
-List%3CT%3E list
+Iterable%3CT%3E iterable
 , Fu
@@ -1218,20 +1218,24 @@
 ontally(
-list
+iterable
 , functi
@@ -1312,139 +1312,28 @@
 lly(
-List%3C?%3E list)%0A%09%7B%0A%09%09return listHorizontally(list, DEFAULT_DELIMITER);%0A%09%7D%0A%09%0A%09@API%0A%09public static String listHorizontally(List%3C?%3E list
+Iterable%3C?%3E iterable
 , St
@@ -1381,19 +1381,24 @@
 lly(
-list
+iterable
 , null,
+ 
  del
@@ -1403,34 +1403,32 @@
 elimiter);%0A%09%7D%0A%09%0A
-%09%0A
 %09@API%0A%09public st
@@ -1460,237 +1460,67 @@
 lly(
-Collection%3C?%3E collection, String delimiter)%0A%09%7B%0A%09%09return listHorizontally(new ArrayList%3C%3E(collection), delimiter);%0A%09%7D%0A%09%0A%09@API%0A%09public static String listHorizontally(Collection%3C?%3E collection)%0A%09%7B%0A%09%09return listHorizontally(collection
+Iterable%3C?%3E iterable)%0A%09%7B%0A%09%09return listHorizontally(iterable
 , DE

Clean up interface of StringListUtil