Structures_RankBuilder.js

'user strict'
const { ErrorCodes } = require('../Errors/ErrorCodes')
const { capitalize } = require('../Utils/Capitalize')
const { isNotPositiveInteger } = require('../Utils/ValidateInteger')
const { InvalidValue, BuilderInvalidNumber, InvalidDataArgument } = require('../Errors/LME')

/** @typedef {import('../../typings').RankData} RankData */
/** @typedef {import('../../typings').Rank} Rank */

/**
 * Represents a rank used in the guild, every rank must have a unique priority.
 */
class RankBuilder {
  /** @type {RankData} - Data of the rank. */
  data

  /**
   * @param {RankData} [data] - Data to build the rank
   */
  constructor (data = {}) {
    if (typeof data !== 'object') throw new InvalidDataArgument(ErrorCodes.InvalidDataArgument)

    this.data = {}

    // Call the setter methods to set the data.
    for (const [key, value] of Object.entries(data)) this[`set${capitalize(key)}`](value)
  }

  /**
   * Sets the nameplate of the rank.
   * @param {String} nameplate - Nameplate of the rank
   * @returns {RankBuilder}
   */
  setNameplate (nameplate) {
    if (typeof nameplate !== 'string') throw new InvalidValue(ErrorCodes.InvalidValue, 'Nameplate', 'a string')

    this.data.nameplate = nameplate

    return this
  }

  /**
   * Sets the color of the rank.
   * @param {String} color - Color of the rank
   * @returns {RankBuilder}
   */
  setColor (color) {
    if (typeof color !== 'string') throw new InvalidValue(ErrorCodes.InvalidValue, 'Color', 'a string')

    this.data.color = color

    return this
  }

  /**
   * Sets the priority of the rank.
   * @param {Number} priority - Priority of the rank, the higher the priority, the higher the rank
   * @returns {RankBuilder}
   */
  setPriority (priority) {
    if (isNotPositiveInteger(priority)) throw new BuilderInvalidNumber(ErrorCodes.BuilderInvalidNumber, 'Priority')

    this.data.priority = priority

    return this
  }

  /**
   * Sets the minimum XP required to get the rank.
   * @param {Number} min - Minimum XP required to get the rank
   * @returns {RankBuilder}
   */
  setMin (min) {
    if (isNotPositiveInteger(min)) throw new BuilderInvalidNumber(ErrorCodes.BuilderInvalidNumber, 'Min')

    this.data.min = min

    return this
  }

  /**
   * Sets the maximum XP required to get the rank (include this level).
   * @param {Number} max - Maximum XP required to get the rank
   * @returns {RankBuilder}
   */
  setMax (max) {
    if (isNotPositiveInteger(max)) throw new BuilderInvalidNumber(ErrorCodes.BuilderInvalidNumber, 'Max')

    this.data.max = max

    return this
  }

  /**
   * Converts the rank builder to a rank object, used to store in the guild.
   * @returns {RankData}
   */
  toJSON () {
    return {
      nameplate: this.data.nameplate,
      color: this.data.color,
      priority: this.data.priority,
      min: this.data.min,
      max: this.data.max
    }
  }
}

module.exports = { RankBuilder }