package com.bonus.core.config.json;

import com.bonus.core.config.WebContext;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.datatype.jsr310.PackageVersion;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.TimeZone;

//@AutoConfiguration(
//   before = {JacksonAutoConfiguration.class}
//)
@Configuration
//@ConditionalOnClass({ObjectMapper.class})
public class JacksonConfiguration {
   public static final StdSerializer<Long> LONG_STD_SERIALIZER;

   @Bean
   Jackson2ObjectMapperBuilderCustomizer objectMapperBuilderCustomizer() {
      return (builder) -> {
         builder.serializerByType(Long.TYPE, LONG_STD_SERIALIZER);
         builder.serializerByType(Long.class, LONG_STD_SERIALIZER);
         builder.locale(Locale.CHINA);
         builder.timeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));
         builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss");
         builder.modules(new Module[]{new SimpleModule(PackageVersion.VERSION) {
            {
               this.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
               this.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
               this.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
               this.addSerializer(Instant.class, new InstantsSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
               this.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
               this.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
               this.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
            }
         }});
      };
   }

   static {
      LONG_STD_SERIALIZER = new StdSerializer<Long>(Long.TYPE) {
         @Override
         public void serialize(Long value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            if (value == null) {
               jsonGenerator.writeNull();
            } else {
               Optional<HttpServletRequest> requestOptional = WebContext.get().getRequest();
               if ((Boolean)requestOptional.map((request) -> {
                  return Objects.isNull(request.getHeader("User-Agent")) || request.getHeader("User-Agent").contains("okhttp");
               }).orElse(false)) {
                  jsonGenerator.writeNumber(value);
               } else {
                  jsonGenerator.writeString(value.toString());
               }
            }
         }
      };
   }
}
