package com.diagbot.idc;


import com.diagbot.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.util.Calendar;

/**
 * @Description: 可见id每秒递增
 * @author: gaodm
 * @time: 2018/9/5 10:45
 */
@Slf4j
public class VisibleIdCreater extends AbstractIdCreater<Integer> {

    private long lastTimestamp = -1L;

    private long sequence = 0L;
    private long sequenceMask = 9999;

    public VisibleIdCreater(int machineId, int dataCenterId) {
        super(machineId, dataCenterId);
    }

    @Override
    /**
     *  对外id生成规则
     *  180905123451110001
     *  180905 - 12345 -  1   -  1   -     1     - 0001
     *   日期 -  秒数  - 业务 - 机器 - 数据中心 - 秒内自增
     *  @param type 业务id 1.订单 2.交易 3.退款
     *  @return 生成的id
     */
    public synchronized Long getNextId(Integer type) {

        Calendar calendar = Calendar.getInstance();

        long timestamp = timeGen() / 1000;

        if (timestamp < lastTimestamp) {
            log.error(String.format("clock is moving backwards. Rejecting requests until %d.", lastTimestamp));
            throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }

        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1);
            if (sequence > sequenceMask) {
                //timestamp = tilNextMillis(lastTimestamp);
                log.error(String.format("id creater sequence is full. wait to next time"));
                return null;
            }
        } else {
            sequence = getNewSequence();
        }

        lastTimestamp = timestamp;

        String date = DateUtil.format(calendar.getTime(), "yyMMdd");
        long seconds = DateUtils.getFragmentInSeconds(calendar, Calendar.DAY_OF_YEAR);

        return Long.valueOf(date + String.format("%05d", seconds) + String.valueOf(type) + machineId + dataCenterId + sequence);
    }

    private long getNewSequence() {
        return RandomUtils.nextInt(1000, 2000);
    }

}
