class NameCollisionError < RuntimeError; end
class NameFormatError < RuntimeError; end

class Robot
  attr_accessor :name

  @@registry

  def initialize(args = {})
    @@registry ||= []
    @name_generator = args[:name_generator]

    if @name_generator
      @name = @name_generator.call
    else
      @name = generate_name
    end

    # TODO Move error handling out of initilize. It really belongs
    # in the generate_name method.
    check_name_format
    check_name_collision
    @@registry << @name
  end

  def generate_name
    temp_name = ''
    2.times { temp_name << ('A'..'Z').to_a.sample }
    3.times { temp_name << rand(10).to_s }
    temp_name
  end

  def check_name_format
    unless name =~ /[[:alpha:]]{2}[[:digit:]]{3}/
      raise NameFormatError,
        'Robot name should be 2 letters and 3 numbers. Ex: AA111'
    end
  end

  def check_name_collision
    if @@registry.include?(name)
      raise NameCollisionError,
        'Robot name is already in the registry'
    end
  end
end

robot = Robot.new
puts "My pet robot's name is #{robot.name}, but we usually call him sparky."

# Errors!
# generator = -> { 'AA111' }
# Robot.new(name_generator: generator)
# Robot.new(name_generator: generator)

class NameCollisionError < RuntimeError; end
class NameFormatError < RuntimeError; end

class Robot
  attr_accessor :name

  @@registry

  def initialize(args = {})
    @@registry ||= []
    @name_generator = args[:name_generator]
    @name = generate_name
    check_name_format
    check_name_collision
    @@registry << @name
  end

  def generate_name
    temp_name = ''

    if @name_generator
      temp_name = @name_generator.call
    else
      2.times { temp_name << ('A'..'Z').to_a.sample }
      3.times { temp_name << rand(10).to_s }
    end

    temp_name
  end

  def check_name_format
    unless name =~ /[[:alpha:]]{2}[[:digit:]]{3}/
      raise NameFormatError,
        'Robot name should be 2 letters and 3 numbers. Ex: AA111'
    end
  end

  def check_name_collision
    if @@registry.include?(name)
      raise NameCollisionError,
        'Robot name is already in the registry'
    end
  end
end

robot = Robot.new
puts "My pet robot's name is #{robot.name}, but we usually call him sparky."

# Errors!
# generator = -> { 'AA111' }
# Robot.new(name_generator: generator)
# Robot.new(name_generator: generator)

Move name generation code out of initialize
Move name generation code out of initialize

There is still a part of this that I don't like. It seems that the
generate_name method should handle the naming errors. However, the
bouncer methods currently depend on the @name instance variable
being set. I see two alternatives: (1) change bouncer methods to
use a passed in variable, or (2) handle the name generation in
another class altogether. I think I like the (2) better because
I'm already fighting this class. It's at a point where I need
some substantial work done before the object is even initialized.
It feels like this work should maybe be done by another class in
this case.
