package com.supervision.util;

import cn.hutool.core.convert.ConverterRegistry;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.map.SafeConcurrentHashMap;

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.time.*;
import java.time.temporal.TemporalAccessor;
import java.util.*;
import java.util.concurrent.atomic.*;

public class ParamTypeConverter {

    private Map<String,Type> typeMap;

    private ParamTypeConverter(){
        defaultConverter();
    }
    public  Object convert(String paramType, Object paramValue) {
        if (Objects.isNull(paramValue)) {
            return null;
        }
        if (null == typeMap.get(paramType)){
            return null;
        }

        return ConverterRegistry.getInstance().convert(typeMap.get(paramType), paramValue);
    }


    private static class SingletonHolder {
        /**
         * 静态初始化器，由JVM来保证线程安全
         */
        private static final ParamTypeConverter INSTANCE = new ParamTypeConverter();
    }

    public static ParamTypeConverter getInstance() {
        return ParamTypeConverter.SingletonHolder.INSTANCE;
    }

    private void defaultConverter() {
        typeMap = new SafeConcurrentHashMap<>();

        // 原始类型转换器
        typeMap.put("int",int.class);
        typeMap.put("long", long.class);
        typeMap.put("byte", byte.class);
        typeMap.put("short", short.class);
        typeMap.put("float", float.class);
        typeMap.put("double", double.class);
        typeMap.put("char", char.class);
        typeMap.put("boolean", boolean.class);

        // 包装类转换器
        typeMap.put("Number", Number.class);
        typeMap.put("Integer", Integer.class);
        typeMap.put("AtomicInteger", AtomicInteger.class);
        typeMap.put("Long", Long.class);
        typeMap.put("LongAdder", LongAdder.class);
        typeMap.put("AtomicLong", AtomicLong.class);
        typeMap.put("Byte", Byte.class);
        typeMap.put("Short", Short.class);
        typeMap.put("Float", Float.class);
        typeMap.put("Double", Double.class);
        typeMap.put("DoubleAdder", DoubleAdder.class);
        typeMap.put("Character", Character.class);
        typeMap.put("Boolean", Boolean.class);
        typeMap.put("AtomicBoolean", AtomicBoolean.class);
        typeMap.put("BigDecimal", BigDecimal.class);
        typeMap.put("BigInteger", BigInteger.class);
        typeMap.put("CharSequence", CharSequence.class);
        typeMap.put("String", String.class);

        // URI and URL
        typeMap.put("URI", URI.class);
        typeMap.put("URL", URL.class);

        // 日期时间
        typeMap.put("Calendar", Calendar.class);
        typeMap.put("java.util.Date", java.util.Date.class);
        typeMap.put("DateTime", DateTime.class);
        typeMap.put("java.sql.Date", java.sql.Date.class);
        typeMap.put("java.sql.Time", java.sql.Time.class);
        typeMap.put("java.sql.Timestamp", java.sql.Timestamp.class);

        // 日期时间 JDK8+
        typeMap.put("TemporalAccessor", TemporalAccessor.class);
        typeMap.put("Instant", Instant.class);
        typeMap.put("LocalDateTime", LocalDateTime.class);
        typeMap.put("LocalDate", LocalDate.class);
        typeMap.put("LocalTime", LocalTime.class);
        typeMap.put("ZonedDateTime", ZonedDateTime.class);
        typeMap.put("OffsetDateTime", OffsetDateTime.class);
        typeMap.put("OffsetTime", OffsetTime.class);
        typeMap.put("DayOfWeek", DayOfWeek.class);
        typeMap.put("Month", Month.class);
        typeMap.put("MonthDay", MonthDay.class);
        typeMap.put("Period", Period.class);
        typeMap.put("Duration", Duration.class);

        // Reference
        typeMap.put("WeakReference", WeakReference.class);
        typeMap.put("SoftReference", SoftReference.class);
        typeMap.put("AtomicReference", AtomicReference.class);

        // AtomicXXXArray
        typeMap.put("AtomicIntegerArray", AtomicIntegerArray.class);
        typeMap.put("AtomicLongArray", AtomicLongArray.class);

        // 其它类型
        typeMap.put("Class", Class.class);
        typeMap.put("TimeZone", TimeZone.class);
        typeMap.put("Locale", Locale.class);
        typeMap.put("Charset", Charset.class);
        typeMap.put("Path", Path.class);
        typeMap.put("Currency", Currency.class);
        typeMap.put("UUID", UUID.class);
        typeMap.put("StackTraceElement", StackTraceElement.class);
        typeMap.put("Optional", Optional.class);
        typeMap.put("Opt", Opt.class);

        typeMap.put("List", List.class);

    }

}
