import * as mc from "@minecraft/server"

/**
 * Define uma propriedade dinâmica para um jogador.
 * @param {mc.Player} player - O jogador para quem definir a propriedade.
 * @param {string} key - A chave da propriedade dinâmica.
 * @param {any} value - O valor da propriedade dinâmica.
 */
export function setProperty(player, key, value) {
    
    const hashedKey = generateHashId(key)
    if (typeof value === "boolean") { player.setDynamicProperty("ld_aw:" + hashedKey, value) }
    else if (typeof value === "number") { player.setDynamicProperty("ld_aw:" + hashedKey, value) }
    else if (typeof value === "string") { player.setDynamicProperty("ld_aw:" + hashedKey, value) }
    else { throw new Error("Tipo de valor não suportado para propriedade dinâmica.") }


}

export function addProperty(player, key, value) { setProperty(player, key, getProperty(key) + value) }

/**
* Obtém uma propriedade dinâmica de um jogador.
* @param {mc.Player} player - O jogador do qual obter a propriedade.
* @param {string} key - A chave da propriedade dinâmica.
* @returns {any} - O valor da propriedade dinâmica.
*/
export function getProperty(player, key) {

  const hashedKey = generateHashId(key)
  return player.getDynamicProperty("ld_aw:" + hashedKey)


}

function generateHashId(id) {

  let hash = 0
  for (let i = 0; i < id.length; i++) {

      const char = id.charCodeAt(i)
      hash = ((hash << 5) - hash) + char
      hash = hash & hash

  }
  return 'id' + hash.toString()

  
}

export class property {
  
  /**
  * @param { mc.Player } player - O jogador do qual obter a propriedade.
  * @param {string} key - A chave da propriedade dinâmica.
  * @param {string} default - A chave da propriedade dinâmica.
  */
  constructor(player, key, defaultValue = 0) {

    this.player = player
    this.key = key
    this.defaultValue = defaultValue
    getProperty(this.player, this.key) === undefined ? this.reset(): null


  }
  reset() {

    console.warn(this.key + "iniciou com o valor de: " + this.defaultValue)
    return setProperty(this.player, this.key, this.defaultValue)


  }
  /**
  * @param { value } number - Novo valor da propriedade.
  */
  set(value) {

    return setProperty(this.player, this.key, value)


  }
  /**
  * @param { value } number - Valor a ser adicionado à propriedade.
  */
  add(value) {

    return setProperty(this.player, this.key, this.get() + value )


  }
  remove(value) {

    return setProperty(this.player, this.key, this.get() - value )


  }
  get() {

    return getProperty(this.player, this.key)


  }


}