package com.engine.common.util.genid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SnowflakeId {
    private static final Logger logger = LoggerFactory.getLogger(SnowflakeId.class);
    private Worker worker;
    private long startTime = this._curSecond();
    private long time;
    private long segment = 0L;
    private long workerId = this.getWorker().getWorkerId();
    private long sequence = 0L;
    private static final long segmentBits = 9L;
    private static final long workerIdBits = 10L;
    private static final long sequenceBits = 13L;
    private static final long timestampShift = 32L;
    private static final long segmentShift = 23L;
    private static final long workerIdShift = 13L;
    private static final long sequenceMask = 8191L;
    private static final long maxSegment = 511L;
    private long twepoch = 1483200000L;
    private long _counter = 0L;

    public SnowflakeId() {
        this.time = this.startTime - this.twepoch;
    }

    public Worker getWorker() {
        return (Worker)(this.worker == null ? new DefaultWorker() : this.worker);
    }

    public void setWorker(Worker worker) {
        this.worker = worker;
    }

    public synchronized long get() {
        long id = this.getNextId();
        this.testSpeedLimit();
        return id;
    }

    public synchronized long[] getRangeId(int sizeOfIds) {
        long[] r = new long[]{this.getNextId(), 0L};
        this.sequence = this.sequence + (long)sizeOfIds - 1L - 1L;
        this._counter = this._counter + (long)sizeOfIds - 1L - 1L;
        if (this.sequence >> 13 > 0L) {
            this.sequence &= 8191L;
            if (this.segment >= 511L) {
                ++this.time;
                this.segment = 0L;
            } else {
                ++this.segment;
            }
        }

        r[1] = this.getNextId();
        this.testSpeedLimit();
        return r;
    }

    private long getNextId() {
        ++this.sequence;
        ++this._counter;
        if (this.sequence >> 13 > 0L) {
            if (this.segment >= 511L) {
                ++this.time;
            } else {
                this.sequence = 0L;
                ++this.segment;
            }
        }

        return this.time << 32 | this.segment << 23 | this.workerId << 13 | this.sequence;
    }

    private long _curSecond() {
        return System.currentTimeMillis() / 1000L;
    }

    private synchronized void testSpeedLimit() {
        long spentTime = this._curSecond() - this.startTime + 1L;
        if (spentTime <= 0L || spentTime << 22 <= this._counter) {
            try {
                this.wait(10L);
                this.testSpeedLimit();
            } catch (Exception var4) {
                logger.error(var4.getMessage(), var4);
            }

        }
    }
}
