/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights reserved. <a>http://www.crunii.com</a>
 */
package com.crunii.micro.common.xml.fast;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer;

/**
 * @author 田平 create 2020年4月30日上午10:57:18
 *
 */
@SuppressWarnings({ "deprecation", "serial" })
public class FixedUntypedObjectDeserializer extends UntypedObjectDeserializer {

	private static final FixedUntypedObjectDeserializer INSTANCE = new FixedUntypedObjectDeserializer();

	private FixedUntypedObjectDeserializer() {

	}

	public static FixedUntypedObjectDeserializer getInstance() {
		return INSTANCE;
	}

	@Override
	@SuppressWarnings({ "unchecked" })
	protected Object mapObject(JsonParser parser, DeserializationContext context) throws IOException {
		@Nullable
		String firstKey;
		JsonToken token = parser.getCurrentToken();
		if (token == JsonToken.START_OBJECT) {
			firstKey = parser.nextFieldName();
		} else if (token == JsonToken.FIELD_NAME) {
			firstKey = parser.getCurrentName();
		} else {
			if (token != JsonToken.END_OBJECT) {
				context.handleUnexpectedToken(handledType(), parser);
			}
			return Collections.emptyMap();
		}

		Map<String, Object> valueByKey = new LinkedHashMap<>();
		String nextKey = firstKey;
		do {
			parser.nextToken();
			Object nextValue = deserialize(parser, context);

			if (valueByKey.containsKey(nextKey)) {
				Object existingValue = valueByKey.get(nextKey);
				if (existingValue instanceof List) {
					List<Object> values = (List<Object>) existingValue;
					values.add(nextValue);
				} else {
					List<Object> values = new ArrayList<>();
					values.add(existingValue);
					values.add(nextValue);
					valueByKey.put(nextKey, values);
				}
			} else {
				valueByKey.put(nextKey, nextValue);
			}

		} while ((nextKey = parser.nextFieldName()) != null);
		return valueByKey;
	}

}
