/*-
 * ~~~~~~licensing~~~~~~
 * test-producers
 * ==========
 * Copyright (C) 2020 - 2025 EmDev LLC
 * ==========
 * You may not use this file except in accordance with the License Terms of the Copyright
 * Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
 * rights to the Software and any copies are the property of the Copyright Holder. Unless
 * it is explicitly allowed the Copyright Holder, the User is prohibited from using the
 * Software for commercial purposes to provide services to third parties.
 * 
 * The Copyright Holder hereby declares that the Software is provided on an "AS IS".
 * Under no circumstances does the Copyright Holder guarantee or promise that the
 * Software provided by him will be suitable or not suitable for the specific purposes
 * of the User, that the Software will meet all commercial and personal subjective
 * expectations of the User, that the Software will work properly, without technical
 * errors, quickly and uninterruptedly.
 * 
 * Under no circumstances shall the Copyright Holder or its Affiliates is not liable
 * to the User for any direct or indirect losses of the User, his expenses or actual
 * damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
 * or damage to data, property, etc.
 * ~~~~~~/licensing~~~~~~
 */
package ru.entaxy.platform.core.producer.executor.generationmodel;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

public class GeneratedHeaders {

	public static final String HEADERS_PROPERTY = "##headers";
	
	
	protected static class PropertyConverter {
		
		public static final String NAME = "name";
		public static final String TYPE = "type";
		public static final String VALUE = "value";
		
		public static void convert(List<?> data, GeneratedHeaders target) {
			for (Object obj: data) {
				if (!(obj instanceof Map<?, ?>))
					continue;
				Map<Object, Object> property = (Map)obj;
				Object name = property.get(NAME);
				if (name == null)
					continue;
				Object value = property.get(VALUE);
				if (value == null)
					continue;
				String type = property.getOrDefault(TYPE, "string").toString().toLowerCase();
				if ("list".equals(type) || (value instanceof List<?>))
					target.append(name.toString(), value);
				else
					target.set(name.toString(), value);
			}
		}
		
	}
	
	public static GeneratedHeaders getHeaders(Map<String, Object> properties) {
		if (!properties.containsKey(HEADERS_PROPERTY))
			properties.put(HEADERS_PROPERTY, new GeneratedHeaders());
		Object obj = properties.get(HEADERS_PROPERTY);
		if (obj instanceof GeneratedHeaders)
			return (GeneratedHeaders)obj;
		GeneratedHeaders gh = new GeneratedHeaders();
		if (obj instanceof List<?>) {
			PropertyConverter.convert((List)obj, gh);
		}
		properties.put(HEADERS_PROPERTY, gh);
		return gh;
	}
	
	Map<String, Object> headers = new HashMap<>();
	
	public void setOrAppend(String name, Object value) {
		if (value instanceof List<?>) {
			append(name, value);
			return;
		}
		if (!this.headers.containsKey(name))
			set(name, value);
		else {
			Object obj = this.headers.get(name);
			if (obj instanceof List<?>)
				append(name, value);
			else
				set(name, value);
		}
	}
	
	public void set(String name, Object value) {
		this.headers.put(name, value);
	}
	
	public void append(String name, Object value) {
		if (!headers.containsKey(name))
			headers.put(name, new LinkedList<Object>());
		else {
			Object obj = headers.get(name);
			if (!(obj instanceof List<?>)) {
				List<Object> list = new LinkedList<Object>();
				list.add(obj);
				headers.put(name, list);
			}
		}
		List<Object> list = (List<Object>)headers.get(name);
		if (value instanceof List<?>)
			list.addAll((List)value);
		else
			list.add(value);
	}
	
	public Map<String, String> getAsStringMap(){
		Map<String, String> result = new HashMap<>();
		for (Entry<String, Object> entry: headers.entrySet())
			result.put(entry.getKey(), getValueAsString(entry.getValue()));
		return result;
	}
	
	protected String getValueAsString(Object value) {
		if (value == null)
			return "";
		if (value instanceof Map<?,?>)
			return getMapValueAsString((Map<?,?>)value);
		if (value instanceof List<?>)
			return getListValueAsString((List)value);
		return value.toString();
	}
	
	protected String getMapValueAsString(Map<?,?> value) {
		return "[" + value.entrySet().stream().filter(e -> e.getKey()!=null)
			.map(e -> e.getKey().toString()+"="+getValueAsString(e.getValue()))
			.collect(Collectors.joining(",")) + "]";
	}
	
	protected String getListValueAsString(List<?> value) {
		return value.stream().map(obj->getValueAsString(obj)).collect(Collectors.joining(","));
	}
}
