package fr.wseduc.webutils;

import org.vertx.java.core.Handler;
import org.vertx.java.core.MultiMap;
import org.vertx.java.core.eventbus.Message;
import org.vertx.java.core.json.JsonArray;
import org.vertx.java.core.json.JsonObject;

import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class Utils {

	public static <T> T getOrElse(T value, T defaultValue) {
		return getOrElse(value, defaultValue, true);
	}

	public static <T> T getOrElse(T value, T defaultValue, boolean allowEmpty) {
		if (value != null && (allowEmpty || !value.toString().trim().isEmpty())) {
			return value;
		}
		return defaultValue;
	}

	public static String inputStreamToString(InputStream in) {
		Scanner scanner = new Scanner(in, "UTF-8");
		String content = scanner.useDelimiter("\\A").next();
		scanner.close();
		return content;
	}

	public static JsonObject validAndGet(JsonObject json, List<String> fields,
				List<String> requiredFields) {
		if (json != null) {
			JsonObject e = json.copy();
			for (String attr: json.getFieldNames()) {
				if (!fields.contains(attr) || e.getValue(attr) == null) {
					e.removeField(attr);
				}
			}
			if (e.toMap().keySet().containsAll(requiredFields)) {
				return e;
			}
		}
		return null;
	}

	public static Either<String, JsonObject> validResult(Message<JsonObject> res) {
		if ("ok".equals(res.body().getString("status"))) {
			JsonObject r = res.body().getObject("result");
			if (r == null) {
				r = res.body();
				r.removeField("status");
			}
			return new Either.Right<>(r);
		} else {
			return new Either.Left<>(res.body().getString("message", ""));
		}
	}

	public static Either<String, JsonArray> validResults(Message<JsonObject> res) {
		if ("ok".equals(res.body().getString("status"))) {
			return new Either.Right<>(res.body().getArray("results", new JsonArray()));
		} else {
			return new Either.Left<>(res.body().getString("message", ""));
		}
	}

	// TODO improve with type and validation
	public static JsonObject jsonFromMultimap(MultiMap attributes) {
		JsonObject json = new JsonObject();
		if (attributes != null) {
			for (Map.Entry<String, String> e: attributes.entries()) {
				json.putString(e.getKey(), e.getValue());
			}
		}
		return json;
	}

	public static <T> boolean defaultValidationError(JsonObject c,
			Handler<Either<String, T>> result, String ... params) {
		return validationError(c, result, "invalid.field", params);
	}

	public static <T> boolean validationError(JsonObject c,
			Handler<Either<String, T>> result, String errorMessage, String ... params) {
		if (c == null) {
			result.handle(new Either.Left<String, T>(errorMessage));
			return true;
		}
		return validationParamsError(result, errorMessage, params);
	}

	public static <T> boolean defaultValidationParamsError(Handler<Either<String, T>> result, String ... params) {
		return validationParamsError(result, "invalid.parameter", params);
	}

	public static <T> boolean validationParamsError(Handler<Either<String, T>> result,
			String errorMessage, String ... params) {
		if (params.length > 0) {
			for (String s : params) {
				if (s == null) {
					result.handle(new Either.Left<String, T>(errorMessage));
					return true;
				}
			}
		}
		return false;
	}

	public static <T extends Enum<T>> T stringToEnum(String name, T defaultValue, Class<T> type) {
		if (name != null) {
			try {
				return Enum.valueOf(type, name);
			} catch (IllegalArgumentException | NullPointerException e) {
				return defaultValue;
			}
		}
		return defaultValue;
	}

}

@@ -3247,24 +3247,528 @@
  false;%0A%09%7D%0A%0A
+%09public static %3CT%3E boolean defaultValidationParamsNull(%0A%09%09%09Handler%3CEither%3CString, T%3E%3E result, Object ... params) %7B%0A%09%09return validationParamsNull(result, %22null.parameter%22, params);%0A%09%7D%0A%0A%09public static %3CT%3E boolean validationParamsNull(Handler%3CEither%3CString, T%3E%3E result,%0A%09%09%09String errorMessage, Object ... params) %7B%0A%09%09if (params.length %3E 0) %7B%0A%09%09%09for (Object s : params) %7B%0A%09%09%09%09if (s == null) %7B%0A%09%09%09%09%09result.handle(new Either.Left%3CString, T%3E(errorMessage));%0A%09%09%09%09%09return true;%0A%09%09%09%09%7D%0A%09%09%09%7D%0A%09%09%7D%0A%09%09return false;%0A%09%7D%0A%0A
 %09public stat

add null params validator