package speiger.src.coreengine.utils.helpers;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;

public class JsonUtil {
	public static JsonObject loadFile(Path path) {
		try(BufferedReader reader = Files.newBufferedReader(path)) {
			return JsonParser.parseReader(reader).getAsJsonObject();
		}
		catch(Exception e) {
			e.printStackTrace();
			return new JsonObject();
		}
	}
	
	public static JsonObject loadFile(File file) {
		try(Reader reader = new BufferedReader(new FileReader(file))) {
			return JsonParser.parseReader(reader).getAsJsonObject();
		}
		catch(Exception e) {
			e.printStackTrace();
			return new JsonObject();
		}
	}
	
	public static JsonObject loadFile(InputStream stream) {
		try(Reader reader = new BufferedReader(new InputStreamReader(stream))) {
			return JsonParser.parseReader(reader).getAsJsonObject();
		}
		catch(Exception e) {
			e.printStackTrace();
			return new JsonObject();
		}
	}
	
	public static void iterate(JsonElement element, Consumer<JsonObject> listener) {
		if(element.isJsonObject()) listener.accept(element.getAsJsonObject());
		else if(element.isJsonArray()) {
			JsonArray array = element.getAsJsonArray();
			for(int i = 0,m = array.size();i < m;i++) {
				iterate(array.get(i), listener);
			}
		}
	}
	
	public static <T> void iterate(JsonElement element, T input, BiConsumer<JsonObject, T> listener) {
		if(element.isJsonObject()) listener.accept(element.getAsJsonObject(), input);
		else if(element.isJsonArray()) {
			JsonArray array = element.getAsJsonArray();
			for(int i = 0,m = array.size();i < m;i++) {
				iterate(array.get(i), input, listener);
			}
		}
	}
	
	public static void iterateValues(JsonElement element, Consumer<JsonPrimitive> result) {
		if(element == null) return;
		if(element.isJsonPrimitive()) result.accept(element.getAsJsonPrimitive());
		else if(element.isJsonArray()) {
			JsonArray array = element.getAsJsonArray();
			for(int i = 0,m = array.size();i < m;i++) {
				iterateValues(array.get(i), result);
			}
		}
	}
	
	public static boolean getOrDefault(JsonObject obj, String name, boolean defaultValue) {
		JsonElement el = obj.get(name);
		return el == null ? defaultValue : el.getAsBoolean();
	}
	
	public static byte getOrDefault(JsonObject obj, String name, byte defaultValue) {
		JsonElement el = obj.get(name);
		return el == null ? defaultValue : el.getAsByte();
	}
	
	public static short getOrDefault(JsonObject obj, String name, short defaultValue) {
		JsonElement el = obj.get(name);
		return el == null ? defaultValue : el.getAsShort();
	}
	
	public static int getOrDefault(JsonObject obj, String name, int defaultValue) {
		JsonElement el = obj.get(name);
		return el == null ? defaultValue : el.getAsInt();
	}
	
	public static long getOrDefault(JsonObject obj, String name, long defaultValue) {
		JsonElement el = obj.get(name);
		return el == null ? defaultValue : el.getAsLong();
	}
	
	public static float getOrDefault(JsonObject obj, String name, float defaultValue) {
		JsonElement el = obj.get(name);
		return el == null ? defaultValue : el.getAsFloat();
	}
	
	public static double getOrDefault(JsonObject obj, String name, double defaultValue) {
		JsonElement el = obj.get(name);
		return el == null ? defaultValue : el.getAsDouble();
	}
	
	public static String getOrDefault(JsonObject obj, String name, String defaultValue) {
		JsonElement el = obj.get(name);
		return el == null ? defaultValue : el.getAsString();
	}
	
	public static JsonArray toArray(byte[] values) {
		JsonArray array = new JsonArray();
		for(int i = 0,m = values.length;i < m;i++) {
			array.add(values[i]);
		}
		return array;
	}
	
	public static JsonArray toArray(short[] values) {
		JsonArray array = new JsonArray();
		for(int i = 0,m = values.length;i < m;i++) {
			array.add(values[i]);
		}
		return array;
	}
	
	public static JsonArray toArray(int[] values) {
		JsonArray array = new JsonArray();
		for(int i = 0,m = values.length;i < m;i++) {
			array.add(values[i]);
		}
		return array;
	}
	
	public static JsonArray toArray(long[] values) {
		JsonArray array = new JsonArray();
		for(int i = 0,m = values.length;i < m;i++) {
			array.add(values[i]);
		}
		return array;
	}
	
	public static JsonArray toArray(float[] values) {
		JsonArray array = new JsonArray();
		for(int i = 0,m = values.length;i < m;i++) {
			array.add(values[i]);
		}
		return array;
	}
	
	public static JsonArray toArray(double[] values) {
		JsonArray array = new JsonArray();
		for(int i = 0,m = values.length;i < m;i++) {
			array.add(values[i]);
		}
		return array;
	}
	
	public static JsonArray toArray(Number[] values) {
		JsonArray array = new JsonArray();
		for(int i = 0,m = values.length;i < m;i++) {
			array.add(values[i]);
		}
		return array;
	}
	
	public static JsonArray toArray(List<Number> values) {
		JsonArray array = new JsonArray();
		for(int i = 0,m = values.size();i < m;i++) {
			array.add(values.get(i));
		}
		return array;
	}
	
	public static Number[] parseArray(JsonArray array) {
		Number[] data = new Number[array.size()];
		for(int i = 0,m = data.length;i < m;i++) {
			data[i] = array.get(i).getAsNumber();
		}
		return data;
	}
	
	public static byte[] parseByteArray(JsonArray array) {
		byte[] data = new byte[array.size()];
		for(int i = 0,m = data.length;i < m;i++) {
			data[i] = array.get(i).getAsByte();
		}
		return data;
	}
	
	public static short[] parseShortArray(JsonArray array) {
		short[] data = new short[array.size()];
		for(int i = 0,m = data.length;i < m;i++) {
			data[i] = array.get(i).getAsShort();
		}
		return data;
	}
	
	public static int[] parseIntArray(JsonArray array) {
		int[] data = new int[array.size()];
		for(int i = 0,m = data.length;i < m;i++) {
			data[i] = array.get(i).getAsInt();
		}
		return data;
	}
	
	public static long[] parseLongArray(JsonArray array) {
		long[] data = new long[array.size()];
		for(int i = 0,m = data.length;i < m;i++) {
			data[i] = array.get(i).getAsLong();
		}
		return data;
	}
	
	public static float[] parseFloatArray(JsonArray array) {
		float[] data = new float[array.size()];
		for(int i = 0,m = data.length;i < m;i++) {
			data[i] = array.get(i).getAsFloat();
		}
		return data;
	}
	
	public static double[] parseDoubleArray(JsonArray array) {
		double[] data = new double[array.size()];
		for(int i = 0,m = data.length;i < m;i++) {
			data[i] = array.get(i).getAsDouble();
		}
		return data;
	}
}
