text: 'use strict';
  
  const Long = require('long');
  
  // Discord epoch (2015-01-01T00:00:00.000Z)
  const EPOCH = 1420070400000;
  let INCREMENT = 0;
  
  /**
   * A container for useful snowflake-related methods.
   */
  class SnowflakeUtil {
    constructor() {
      throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
    }
  
    /**
     * A Twitter snowflake, except the epoch is 2015-01-01T00:00:00.000Z
     * ```
     * If we have a snowflake '266241948824764416' we can represent it as binary:
     *
     * 64                                          22     17     12          0
     *  000000111011000111100001101001000101000000  00001  00000  000000000000
     *       number of ms since Discord epoch       worker  pid    increment
     * ```
     * @typedef {string} Snowflake
     */
  
    /**
     * Generates a Discord snowflake.
     * <info>This hardcodes the worker ID as 1 and the process ID as 0.</info>
     * @param {number|Date} [timestamp=Date.now()] Timestamp or date of the snowflake to generate
     * @returns {Snowflake} The generated snowflake
     */
    static generate(timestamp) { timestamp=timestamp||Date.now();
      if (timestamp instanceof Date) timestamp = timestamp.getTime();
      if (typeof timestamp !== 'number' || isNaN(timestamp)) {
        throw new TypeError(
          `"timestamp" argument must be a number (received ${isNaN(timestamp) ? 'NaN' : typeof timestamp})`
        );
      }
      if (INCREMENT >= 4095) INCREMENT = 0;
      const BINARY = `${pad((timestamp - EPOCH).toString(2), 42)}0000100000${pad((INCREMENT++).toString(2), 12)}`;
      return Long.fromString(BINARY, 2).toString();
    }
  
    /**
     * A deconstructed snowflake.
     * @typedef {Object} DeconstructedSnowflake
     * @property {number} timestamp Timestamp the snowflake was created
     * @property {Date} date Date the snowflake was created
     * @property {number} workerID Worker ID in the snowflake
     * @property {number} processID Process ID in the snowflake
     * @property {number} increment Increment in the snowflake
     * @property {string} binary Binary representation of the snowflake
     */
  
    /**
     * Deconstructs a Discord snowflake.
     * @param {Snowflake} snowflake Snowflake to deconstruct
     * @returns {DeconstructedSnowflake} Deconstructed snowflake
     */
    static deconstruct(snowflake) {
      const BINARY = pad(Long.fromString(snowflake).toString(2), 64);
      const res = {
        timestamp: parseInt(BINARY.substring(0, 42), 2) + EPOCH,
        workerID: parseInt(BINARY.substring(42, 47), 2),
        processID: parseInt(BINARY.substring(47, 52), 2),
        increment: parseInt(BINARY.substring(52, 64), 2),
        binary: BINARY,
      };
      Object.defineProperty(res, 'date', {
        get: function get() { return new Date(this.timestamp); },
        enumerable: true,
      });
      return res;
    }
  }
  
  function pad(v, n, c) {
    return String(v).length >= n ? String(v) : (String(c===undefined?'0':c).repeat(n) + v).slice(-n);
  }
  
  module.exports = SnowflakeUtil;
  