package com.ssyf.common.core.util;

import cn.hutool.core.date.DateUtil;

import java.text.DecimalFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;

/**
 * 流程编码生成工具
 * @author huwei
 * @date 2023/2/17 14:53
 */
public class SerialNumberUtil {

    /**
     * 同时间点流水号控制map
     */
    private static Map<String, AtomicInteger> sameTimeSerialMap = new ConcurrentHashMap<>();

    public static String create(){
        return create(null ,"yyyyMMddHHmmss" ,4);
    }

    /**
     * 生成流水号；
     * 号码整体长度等于：前缀长度 + 格式化日期的长度 + 流水号的长度；
     * @param prefix 前缀
     * @param datetimeFormat 日期格式化样式
     * @param serialLength 流水号长度
     * @return
     */
    public static String create(String prefix , String datetimeFormat , int serialLength){
        String millisKey = DateUtil.format(new Date() ,datetimeFormat);
        Lock lock = SimpleLockerUtil.getLocker(millisKey);
        lock.lock();
        try{
            AtomicInteger atomicInteger = sameTimeSerialMap.get(millisKey);
            if(atomicInteger == null){
                atomicInteger = new AtomicInteger(0);
                sameTimeSerialMap.put(millisKey ,atomicInteger);
            }
            int serial = atomicInteger.incrementAndGet();
            StringBuilder serialFormatCode = new StringBuilder();
            for(int i = 0 ;i < serialLength ;++i){
                serialFormatCode.append("0");
            }
            StringBuilder result = new StringBuilder();
            result.append(prefix != null ? prefix : "");
            result.append(millisKey);
            result.append(new DecimalFormat(serialFormatCode.toString()).format(serial));

            int count = SimpleLockerUtil.getReferenceCount(millisKey);
            if(count <= 0){
                sameTimeSerialMap.remove(millisKey);
            }
            return result.toString();
        }finally {
            lock.unlock();
        }
    }
}
