// To use this code, add the following Maven dependency to your project:
//
//
//     com.fasterxml.jackson.core     : jackson-databind          : 2.9.0
//     com.fasterxml.jackson.datatype : jackson-datatype-jsr310   : 2.9.0
//
// Import this package:
//
//     import io.quicktype.Converter;
//
// Then you can deserialize a JSON string with
//
//     PayloadT data = Converter.PayloadFromJsonString(jsonString);
//     EnvelopeT data = Converter.EnvelopeFromJsonString(jsonString);
//     PayloadT data = Converter.PayloadTFromJsonString(jsonString);
//     Map<String, Object> data = Converter.TFromJsonString(jsonString);
//     EnvelopeT data = Converter.EnvelopeTFromJsonString(jsonString);
//     PayloadT1 data = Converter.PayloadT1FromJsonString(jsonString);
//     Map<String, Object> data = Converter.T1FromJsonString(jsonString);

package io.quicktype;

import java.io.IOException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.*;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;

public class Converter {
    // Date-time helpers

    private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()
            .appendOptional(DateTimeFormatter.ISO_DATE_TIME)
            .appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
            .appendOptional(DateTimeFormatter.ISO_INSTANT)
            .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SX"))
            .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssX"))
            .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
            .toFormatter()
            .withZone(ZoneOffset.UTC);

    public static OffsetDateTime parseDateTimeString(String str) {
        return ZonedDateTime.from(Converter.DATE_TIME_FORMATTER.parse(str)).toOffsetDateTime();
    }

    private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder()
            .appendOptional(DateTimeFormatter.ISO_TIME)
            .appendOptional(DateTimeFormatter.ISO_OFFSET_TIME)
            .parseDefaulting(ChronoField.YEAR, 2020)
            .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
            .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
            .toFormatter()
            .withZone(ZoneOffset.UTC);

    public static OffsetTime parseTimeString(String str) {
        return ZonedDateTime.from(Converter.TIME_FORMATTER.parse(str)).toOffsetDateTime().toOffsetTime();
    }
    // Serialize/deserialize helpers

    public static PayloadT PayloadFromJsonString(String json) throws IOException {
        return getPayloadObjectReader().readValue(json);
    }

    public static String PayloadToJsonString(PayloadT obj) throws JsonProcessingException {
        return getPayloadObjectWriter().writeValueAsString(obj);
    }

    public static EnvelopeT EnvelopeFromJsonString(String json) throws IOException {
        return getEnvelopeObjectReader().readValue(json);
    }

    public static String EnvelopeToJsonString(EnvelopeT obj) throws JsonProcessingException {
        return getEnvelopeObjectWriter().writeValueAsString(obj);
    }

    public static PayloadT PayloadTFromJsonString(String json) throws IOException {
        return getPayloadTObjectReader().readValue(json);
    }

    public static String PayloadTToJsonString(PayloadT obj) throws JsonProcessingException {
        return getPayloadTObjectWriter().writeValueAsString(obj);
    }

    public static Map<String, Object> TFromJsonString(String json) throws IOException {
        return getTObjectReader().readValue(json);
    }

    public static String TToJsonString(Map<String, Object> obj) throws JsonProcessingException {
        return getTObjectWriter().writeValueAsString(obj);
    }

    public static EnvelopeT EnvelopeTFromJsonString(String json) throws IOException {
        return getEnvelopeTObjectReader().readValue(json);
    }

    public static String EnvelopeTToJsonString(EnvelopeT obj) throws JsonProcessingException {
        return getEnvelopeTObjectWriter().writeValueAsString(obj);
    }

    public static PayloadT1 PayloadT1FromJsonString(String json) throws IOException {
        return getPayloadT1ObjectReader().readValue(json);
    }

    public static String PayloadT1ToJsonString(PayloadT1 obj) throws JsonProcessingException {
        return getPayloadT1ObjectWriter().writeValueAsString(obj);
    }

    public static Map<String, Object> T1FromJsonString(String json) throws IOException {
        return getT1ObjectReader().readValue(json);
    }

    public static String T1ToJsonString(Map<String, Object> obj) throws JsonProcessingException {
        return getT1ObjectWriter().writeValueAsString(obj);
    }

    private static ObjectReader PayloadReader;
    private static ObjectWriter PayloadWriter;

    private static void instantiatePayloadMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.findAndRegisterModules();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        SimpleModule module = new SimpleModule();
        module.addDeserializer(OffsetDateTime.class, new JsonDeserializer<OffsetDateTime>() {
            @Override
            public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                String value = jsonParser.getText();
                return Converter.parseDateTimeString(value);
            }
        });
        mapper.registerModule(module);
        PayloadReader = mapper.readerFor(PayloadT.class);
        PayloadWriter = mapper.writerFor(PayloadT.class);
    }

    private static ObjectReader getPayloadObjectReader() {
        if (PayloadReader == null) instantiatePayloadMapper();
        return PayloadReader;
    }

    private static ObjectWriter getPayloadObjectWriter() {
        if (PayloadWriter == null) instantiatePayloadMapper();
        return PayloadWriter;
    }

    private static ObjectReader EnvelopeReader;
    private static ObjectWriter EnvelopeWriter;

    private static void instantiateEnvelopeMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.findAndRegisterModules();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        SimpleModule module = new SimpleModule();
        module.addDeserializer(OffsetDateTime.class, new JsonDeserializer<OffsetDateTime>() {
            @Override
            public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                String value = jsonParser.getText();
                return Converter.parseDateTimeString(value);
            }
        });
        mapper.registerModule(module);
        EnvelopeReader = mapper.readerFor(EnvelopeT.class);
        EnvelopeWriter = mapper.writerFor(EnvelopeT.class);
    }

    private static ObjectReader getEnvelopeObjectReader() {
        if (EnvelopeReader == null) instantiateEnvelopeMapper();
        return EnvelopeReader;
    }

    private static ObjectWriter getEnvelopeObjectWriter() {
        if (EnvelopeWriter == null) instantiateEnvelopeMapper();
        return EnvelopeWriter;
    }

    private static ObjectReader PayloadTReader;
    private static ObjectWriter PayloadTWriter;

    private static void instantiatePayloadTMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.findAndRegisterModules();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        SimpleModule module = new SimpleModule();
        module.addDeserializer(OffsetDateTime.class, new JsonDeserializer<OffsetDateTime>() {
            @Override
            public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                String value = jsonParser.getText();
                return Converter.parseDateTimeString(value);
            }
        });
        mapper.registerModule(module);
        PayloadTReader = mapper.readerFor(PayloadT.class);
        PayloadTWriter = mapper.writerFor(PayloadT.class);
    }

    private static ObjectReader getPayloadTObjectReader() {
        if (PayloadTReader == null) instantiatePayloadTMapper();
        return PayloadTReader;
    }

    private static ObjectWriter getPayloadTObjectWriter() {
        if (PayloadTWriter == null) instantiatePayloadTMapper();
        return PayloadTWriter;
    }

    private static ObjectReader TReader;
    private static ObjectWriter TWriter;

    private static void instantiateTMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.findAndRegisterModules();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        SimpleModule module = new SimpleModule();
        module.addDeserializer(OffsetDateTime.class, new JsonDeserializer<OffsetDateTime>() {
            @Override
            public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                String value = jsonParser.getText();
                return Converter.parseDateTimeString(value);
            }
        });
        mapper.registerModule(module);
        TReader = mapper.readerFor(Map.class);
        TWriter = mapper.writerFor(Map.class);
    }

    private static ObjectReader getTObjectReader() {
        if (TReader == null) instantiateTMapper();
        return TReader;
    }

    private static ObjectWriter getTObjectWriter() {
        if (TWriter == null) instantiateTMapper();
        return TWriter;
    }

    private static ObjectReader EnvelopeTReader;
    private static ObjectWriter EnvelopeTWriter;

    private static void instantiateEnvelopeTMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.findAndRegisterModules();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        SimpleModule module = new SimpleModule();
        module.addDeserializer(OffsetDateTime.class, new JsonDeserializer<OffsetDateTime>() {
            @Override
            public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                String value = jsonParser.getText();
                return Converter.parseDateTimeString(value);
            }
        });
        mapper.registerModule(module);
        EnvelopeTReader = mapper.readerFor(EnvelopeT.class);
        EnvelopeTWriter = mapper.writerFor(EnvelopeT.class);
    }

    private static ObjectReader getEnvelopeTObjectReader() {
        if (EnvelopeTReader == null) instantiateEnvelopeTMapper();
        return EnvelopeTReader;
    }

    private static ObjectWriter getEnvelopeTObjectWriter() {
        if (EnvelopeTWriter == null) instantiateEnvelopeTMapper();
        return EnvelopeTWriter;
    }

    private static ObjectReader PayloadT1Reader;
    private static ObjectWriter PayloadT1Writer;

    private static void instantiatePayloadT1Mapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.findAndRegisterModules();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        SimpleModule module = new SimpleModule();
        module.addDeserializer(OffsetDateTime.class, new JsonDeserializer<OffsetDateTime>() {
            @Override
            public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                String value = jsonParser.getText();
                return Converter.parseDateTimeString(value);
            }
        });
        mapper.registerModule(module);
        PayloadT1Reader = mapper.readerFor(PayloadT1.class);
        PayloadT1Writer = mapper.writerFor(PayloadT1.class);
    }

    private static ObjectReader getPayloadT1ObjectReader() {
        if (PayloadT1Reader == null) instantiatePayloadT1Mapper();
        return PayloadT1Reader;
    }

    private static ObjectWriter getPayloadT1ObjectWriter() {
        if (PayloadT1Writer == null) instantiatePayloadT1Mapper();
        return PayloadT1Writer;
    }

    private static ObjectReader T1Reader;
    private static ObjectWriter T1Writer;

    private static void instantiateT1Mapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.findAndRegisterModules();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        SimpleModule module = new SimpleModule();
        module.addDeserializer(OffsetDateTime.class, new JsonDeserializer<OffsetDateTime>() {
            @Override
            public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
                String value = jsonParser.getText();
                return Converter.parseDateTimeString(value);
            }
        });
        mapper.registerModule(module);
        T1Reader = mapper.readerFor(Map.class);
        T1Writer = mapper.writerFor(Map.class);
    }

    private static ObjectReader getT1ObjectReader() {
        if (T1Reader == null) instantiateT1Mapper();
        return T1Reader;
    }

    private static ObjectWriter getT1ObjectWriter() {
        if (T1Writer == null) instantiateT1Mapper();
        return T1Writer;
    }
}
