package cn.com.ty.lift.ud.neety.protocol;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSONArray;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

import java.lang.reflect.Type;
import java.util.Set;
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;

/**
 * Gson可以将json字符串转换成map, 但是在转成map时, 原json字符串中的int , long型的数字会默认被转换成double类型 , 导致数字会多一个小数点 , 如 1 会转成 1.0。
 * 
 * @author sKing
 *
 */
public class GsonTypeAdapter extends TypeAdapter<RoomVo> {

    public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
        @SuppressWarnings("unchecked")
        @Override
        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
            if (type.getRawType() == RoomVo.class) {
                return (TypeAdapter<T>)new GsonTypeAdapter(gson);
            }
            return null;
        }
    };

    private final Gson gson;

    GsonTypeAdapter(Gson gson) {
        this.gson = gson;
    }

    @Override
    public void write(JsonWriter out, RoomVo value) throws IOException {
        if (value == null) {
            out.nullValue();
            return;
        }

        out.beginObject();
        out.name("userId");
        gson.getAdapter(String.class).write(out, value.getUserId());
        out.name("unreadNum");
        gson.getAdapter(Integer.class).write(out, value.getUnreadNum());
        out.endObject();
    }

    @Override
    public RoomVo read(JsonReader in) throws IOException {
        RoomVo data = new RoomVo();
        Map<String, Object> dataMap = (Map<String, Object>)readInternal(in);
        data.setUserId(dataMap.get("userId").toString());
        data.setUnreadNum(Integer.parseInt(dataMap.get("unreadNum").toString()));
        return data;
    }

    private Object readInternal(JsonReader in) throws IOException {
        JsonToken token = in.peek();
        switch (token) {
            case BEGIN_ARRAY:
                List<Object> list = new ArrayList<Object>();
                in.beginArray();
                while (in.hasNext()) {
                    list.add(readInternal(in));
                }
                in.endArray();
                return list;

            case BEGIN_OBJECT:
                Map<String, Object> map = new LinkedTreeMap<String, Object>();
                in.beginObject();
                while (in.hasNext()) {
                    map.put(in.nextName(), readInternal(in));
                }
                in.endObject();
                return map;

            case STRING:
                return in.nextString();

            case NUMBER:
                // 将其作为一个字符串读取出来
                String numberStr = in.nextString();
                // 返回的numberStr不会为null
                if (numberStr.contains(".") || numberStr.contains("e") || numberStr.contains("E")) {
                    return Double.parseDouble(numberStr);
                }
                return Long.parseLong(numberStr);

            case BOOLEAN:
                return in.nextBoolean();

            case NULL:
                in.nextNull();
                return null;

            default:
                throw new IllegalStateException();
        }
    }

    public static Gson buildGson() {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.registerTypeAdapterFactory(GsonTypeAdapter.FACTORY);
        return gsonBuilder.create();
    }

    public static Gson getGson() {
        Gson gson = new GsonBuilder().registerTypeAdapter(HashMap.class, new JsonDeserializer<HashMap>() {
            @Override
            public HashMap<String, Object> deserialize(JsonElement json, Type typeOfT,
                JsonDeserializationContext context) throws JsonParseException {
                HashMap<String, Object> resultMap = new HashMap<>();
                JsonObject jsonObject = json.getAsJsonObject();
                Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
                for (Map.Entry<String, JsonElement> entry : entrySet) {
                    resultMap.put(entry.getKey(), entry.getValue());
                }
                return resultMap;
            }

        }).create();
        return gson;
    }

    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        String aaa = "[{\"userId\":1,\"unreadNum\":0}]";
        // List resultList= new ArrayList<>(Arrays.asList(aaa));

        // Map map = getGson().fromJson(aaa, HashMap.class);
        String a = aaa.replace("[", "").replace("]", "");
        System.out.println(a);
//        System.out.println(JSONObject.parseArray(JSONObject.toJSONString(JSONObject.parse(a)),RoomVo.class));
        System.out.println( jsonToList(aaa,RoomVo.class));
    }
    
    /**
     * json 转 List<T>
     */
    public static <T> List<T> jsonToList(String jsonString, Class<T> clazz) {
        @SuppressWarnings("unchecked")
        List<T> ts = (List<T>) JSONArray.parseArray(jsonString, clazz);
        return ts;
    }
}
