/**
 * Copyright 2008-2009. Chongqing CRun Information Industry Co.,Ltd. All rights reserved. <a>http://www.crunii.com</a>
 */
package com.crunii.micro.common.jackson;

import com.crunii.micro.common.utils.DateUtil;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 田平 create 2017年10月27日下午4:31:16
 */
public class DateSerializer extends StdScalarSerializer<Date> implements ContextualSerializer {
	private static final long serialVersionUID = 1L;

	private static final ConcurrentHashMap<String, DateSerializer> FORMAT_SERIALIZER = new ConcurrentHashMap<>(4);

	private String pattern;

	public DateSerializer(Class<Date> t) {
		super(t);
	}

	public DateSerializer(Class<Date> t, String pattern) {
		super(t);
		this.pattern = pattern;
	}

	@Override
	public void serialize(Date value, JsonGenerator gen, SerializerProvider provider) throws IOException {
		if (value != null) {
			if (!StringUtils.hasText(pattern)) {
				gen.writeString(DateUtil.format(value));
			} else {
				gen.writeString(DateUtil.format(value, pattern));
			}
		} else {
			gen.writeNull();
		}
	}

	@Override
	public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
		JsonFormat.Value format = findFormatOverrides(prov, property, Date.class);
		if (format != null && StringUtils.hasText(format.getPattern())) {
			return FORMAT_SERIALIZER.computeIfAbsent(format.getPattern(), key -> new DateSerializer(Date.class, key));
		} else {
			return this;
		}
	}
}
