package cn.com.ty.lift.ud.common;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

/**
 * 生成随机流水号，ID + yyyyMMddHHmmss + 四位随机数
 *
 * @author tao
 * @date
 */
public class RandomizingID {
    /**
     * 随机号时间格式
     */
    private String timeFormatter = "yyyyMMddHHmmss";

    private SimpleDateFormat sdf = null;

    private static SimpleDateFormat nextSecond = new SimpleDateFormat("SSS");

    /**
     * 秒（一秒有多少毫秒）
     */
    private long secondUnit = 1000;

    /**
     * 随机数字位数
     */
    private int randomNumLength = 3;

    /**
     * 编号前缀
     */
    private String prefix = "";

    /**
     * 是否颠倒字符串
     */
    private boolean reverse = false;

    /**
     * 上一次生成时间
     */
    private String preGenTime = "";

    /**
     * 当前时间最大请求数量
     */
    private double maxRequest;

    /**
     * 数字格式
     */
    private String numFormat;

    /**
     * 当前秒内生成订单号的随机数字
     */
    private Set<Long> currentSecondRandomNos = Collections.synchronizedSet(new HashSet<Long>());

    /**
     * 获取流水号   ID + yyyyMMddHHmmss + 四位随机数
     * @return
     */
    public static String getBillId(){
        RandomizingID random = new RandomizingID("ID", "yyyyMMddHHmmss", 4, false);
        String genNewId = random.genNewId();
        return genNewId;
    }



    public RandomizingID() {
        sdf = new SimpleDateFormat(timeFormatter);
    }

    /**
     * @param randomNumLength 随机数字位数
     */
    public RandomizingID(int randomNumLength) {
        this.randomNumLength = randomNumLength;
        this.maxRequest = Math.pow(10, this.randomNumLength);
        this.numFormat = MessageFormat.format("%0{0}d", randomNumLength);
    }

    /**
     * @param timeFormatter   时间格式
     * @param randomNumLength 随机数字位数
     * @param reverse         是否颠倒
     */
    public RandomizingID(String timeFormatter, int randomNumLength, boolean reverse) {
        if (StringUtils.isNotBlank(timeFormatter)) {
            this.timeFormatter = timeFormatter.trim();
            sdf = new SimpleDateFormat(this.timeFormatter);
        }
        this.randomNumLength = randomNumLength;
        this.reverse = reverse;
        this.maxRequest = Math.pow(10, this.randomNumLength);
        this.numFormat = MessageFormat.format("%0{0}d", randomNumLength);
    }

    /**
     * @param prefix          前缀
     * @param timeFormatter   时间格式
     * @param randomNumLength 随机数字位数
     * @param reverse         是否颠倒
     */
    public RandomizingID(String prefix, String timeFormatter, int randomNumLength, boolean reverse) {
        if (StringUtils.isNotBlank(prefix))
            this.prefix = prefix.trim();
        if (StringUtils.isNotBlank(timeFormatter)) {
            this.timeFormatter = timeFormatter.trim();
            sdf = new SimpleDateFormat(this.timeFormatter);
        }
        this.randomNumLength = randomNumLength;
        this.reverse = reverse;
        this.maxRequest = Math.pow(10, this.randomNumLength);
        this.numFormat = MessageFormat.format("%0{0}d", randomNumLength);
    }

    /**
     * 生成随机号
     *
     * @return
     * @author Neo
     * @date 2018年1月18日11:49:27
     */
    public synchronized String genNewId() {
        if (currentSecondRandomNos.size() >= maxRequest) {
            try {
                Thread.currentThread();
                //计算当前秒距离下一秒还有多少毫秒
                long sleepTime = secondUnit - Long.valueOf(nextSecond.format(new Date()));
                // 休息到下一秒
                Thread.sleep(sleepTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        String currentTime = sdf.format(new Date());
        if (!preGenTime.equals(currentTime)) {
            preGenTime = currentTime;
            currentSecondRandomNos.clear();
        }
        // 随机数字
        long random = getRandom();
        currentSecondRandomNos.add(random);

        String formated = String.format(numFormat, random);
        String id = currentTime + formated;
        if (reverse)
            id = StringUtils.reverse(id);
        return prefix + id;
    }

    /**
     * 获得随机数字
     *
     * @return
     * @author Neo
     * @date 2018年1月18日11:49:44
     */
    private Long getRandom() {
        Long random = Math.round(Math.random() * maxRequest);
        if (currentSecondRandomNos.add(random)) {
            return random;
        }
        return getRandom();
    }

    public static void main(String[] args) {
        RandomizingID random = new RandomizingID("ID", "yyyyMMddHHmmss", 4, false);
        String genNewId = random.genNewId();
        System.out.println(genNewId);
    }

}