module Discorb
  #
  # Extended hash class. This is used for storing pair of ID and object.
  class Dictionary[K < _ToS, V] < Array[V]
    #
    # Initialize a new Dictionary.
    #
    # @param [Hash] hash A hash of items to add to the dictionary.
    # @param [Integer] limit The maximum number of items in the dictionary.
    # @param [false, Proc] sort Whether to sort the items in the dictionary.
    def initialize: (
      ?::Hash[untyped, untyped] hash,
      ?limit: Integer?,
      ?sort: bool | Proc
    ) -> void

    #
    # Registers a new item in the dictionary.
    #
    # @param [#to_s] id The ID of the item.
    # @param [Object] body The item to register.
    #
    # @return [self] The dictionary.
    def register: (_ToS id, Object body) -> self

    alias []= register

    #
    # Merges another dictionary into this one.
    #
    # @param [Discorb::Dictionary] other The dictionary to merge.
    def merge: (Discorb::Dictionary[untyped, untyped] other) -> untyped

    #
    # Removes an item from the dictionary.
    #
    # @param [#to_s] id The ID of the item to remove.
    def remove: (_ToS id) -> untyped

    #
    # Get an item from the dictionary.
    #
    # @param [#to_s] id The ID of the item.
    # @return [Object] The item.
    # @return [nil] if the item was not found.
    #
    # @overload get(index)
    #   @param [Integer] index The index of the item.
    #
    #   @return [Object] The item.
    #   @return [nil] if the item is not found.
    def get: (_ToS id) -> V | (Integer index) -> V

    alias [] get

    #
    # Returns the values of the dictionary.
    #
    # @return [Array] The values of the dictionary.
    def values: -> ::Array[V]

    #
    # Checks if the dictionary has an ID.
    #
    # @param [#to_s] id The ID to check.
    #
    # @return [Boolean] `true` if the dictionary has the ID, `false` otherwise.
    def has?: (_ToS id) -> bool

    #
    # Send a message to the array of values.
    def method_missing: (untyped name) -> untyped

    def respond_to_missing?: (
      untyped name,
      untyped args,
      untyped kwargs
    ) -> bool

    def inspect: -> String

    # @return [Integer] The maximum number of items in the dictionary.
    attr_accessor limit: Integer?
  end
end