package org.kne.cloud.network.klalb;

import java.lang.reflect.Type;
import java.util.Objects;

import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;

public class KLALBConfigItem {
	private String Type;

	public String getType() {
		return Type;
	}

	public void setType(String type) {
		Type = type;
	}

	@Override
	public String toString() {
		return "KLALBConfigItem [Type=" + Type + "]";
	}

	public KLALBConfigItem(String type) {
		super();
		Type = type;
	}

	@Override
	public int hashCode() {
		return Objects.hash(Type);
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		KLALBConfigItem other = (KLALBConfigItem) obj;
		return Objects.equals(Type, other.Type);
	}
	public static JsonDeserializer<KLALBConfigItem>getDefaultJsonDeserializer(){
		return new JsonDeserializer<KLALBConfigItem>() {
			
			@Override
			public KLALBConfigItem deserialize(JsonElement arg0, Type arg1, JsonDeserializationContext arg2)
					throws JsonParseException {
				if(arg0.isJsonObject()) {
					JsonObject jobj=(JsonObject) arg0;
					String s=jobj.get("Type").getAsString();
					switch(s) {
					case "KLALBController":
						normalizeLegacyControllerKeys(jobj);
						return arg2.deserialize(arg0, new TypeToken<KLALBControllerConfigItem>() {}.getType());
					case "SocketBridge":
						return arg2.deserialize(arg0, new TypeToken<SocketBridgeConfigItem>() {}.getType());
					default:
						return arg2.deserialize(arg0, new TypeToken<UnknownKLALBConfigItem>() {}.getType());
					}
				}
				throw new JsonParseException("not a object:"+arg0);
			}

			/**
			 * 将历史命名错误的配置键归一化为当前键名（仅在当前键名不存在时生效）：
			 * openConnections/lineTable → externalEndpoints，
			 * denyConnectionQuery/denyLineTableQuery → denyExternalEndpointQuery，
			 * denyConnectionBroadcast/denyLineTableBroadcast → denyExternalEndpointBroadcast。
			 */
			private void normalizeLegacyControllerKeys(JsonObject jobj) {
				renameLegacyKey(jobj,"externalEndpoints","openConnections","OpenConnections","lineTable","LineTable");
				renameLegacyKey(jobj,"denyExternalEndpointQuery","denyConnectionQuery","denyLineTableQuery");
				renameLegacyKey(jobj,"denyExternalEndpointBroadcast","denyConnectionBroadcast","denyLineTableBroadcast");
				if (!jobj.has("webListen") && jobj.has("webPort") && !jobj.get("webPort").isJsonNull()) {
					int port = jobj.get("webPort").getAsInt();
					jobj.add("webListen", new JsonPrimitive("http://0.0.0.0:" + port));
				}
				jobj.remove("webPort");
			}

			private void renameLegacyKey(JsonObject jobj, String newKey, String... legacyKeys) {
				if (jobj.has(newKey)) {
					for (String legacyKey : legacyKeys) {
						jobj.remove(legacyKey);
					}
					return;
				}
				for (String legacyKey : legacyKeys) {
					if (jobj.has(legacyKey)) {
						jobj.add(newKey, jobj.get(legacyKey));
						jobj.remove(legacyKey);
						return;
					}
				}
			}
		};
	}
	public static JsonSerializer<KLALBConfigItem>getDefaultJsonSerializer(){
		return new JsonSerializer<KLALBConfigItem>() {
			
			@Override
			public JsonElement serialize(KLALBConfigItem arg0, Type arg1, JsonSerializationContext arg2) {
				if(arg0 instanceof KLALBControllerConfigItem) {
					return arg2.serialize(arg0, new TypeToken<KLALBControllerConfigItem>() {}.getType());
				}
				if(arg0 instanceof SocketBridgeConfigItem) {
					return arg2.serialize(arg0, new TypeToken<SocketBridgeConfigItem>() {}.getType());
				}
				return arg2.serialize(arg0, new TypeToken<UnknownKLALBConfigItem>() {}.getType());
			}
		};
	}
	
	public static void registerToGsonBuilder(GsonBuilder gsonBuilder) {
		gsonBuilder.registerTypeAdapter(KLALBConfigItem.class, getDefaultJsonDeserializer());
		gsonBuilder.registerTypeAdapter(KLALBConfigItem.class, getDefaultJsonSerializer());
	}
}
