require './core/utils/user_utils'
require './core/utils/logger_utils'

# Reports the Top 5 Slowest User Type initializations from Heimdall to STDOUT
class UserInitDurationFormatter
  RSpec::Core::Formatters.register self, :dump_summary

  def initialize(notification)
  end

  def dump_summary(notification)
    ordered_types = sorted_durations
    return unless ordered_types.length > 0

    puts "\nTop 5 Slowest User Type Retrievals:"
    ordered_types[0...5].each do |type|
      puts "\t#{type[:type]}: #{type[:duration].round(2)} seconds"
    end
  end

  # Loops through registered users and compiles durations for each user_type
  # For example, user_a's wait durations in separate different specs will be added together
  # @return [Hash] Key containing the UserType name, value containing the total duration it waited to initialize
  private def compile_durations
    type_names = {}

    UserType.registered_users.each do |id, types|
      types.each do |type|
        if type.user_creation_duration.nil?
          logger.warn "[UserInitDurationFormatter] Found nil value for #{type.type}, spec id: #{id}"
          next
        end

        if type_names.has_key?(type.type)
          type_names[type.type] += type.user_creation_duration # Compile with the existing duration value
        else
          type_names[type.type] = type.user_creation_duration # First of this type, assign its duration
        end
      end
    end

    return type_names
  end

  # @return [Array<Hash>] Array of UserType durations sorted from largest to smallest duration time
  #   :type contains the usertype name
  #   :duration contains its duration
  private def sorted_durations
    durations = compile_durations
    ordered = []

    durations.each do |type_name, duration|
      ordered << {type: type_name, duration: duration}
    end

    ordered.sort_by! { |x| x[:duration] }
    return ordered.reverse
  end
end
