require 'facets/core/kernel/instance_assign'
require 'facets/core/kernel/assign_from'

module Kernel

  # Set setter methods and/or vars using a hash (or assoc array).
  # #assign_with is a meta-programming method, which allows you to
  # use a hash to do any kind of variable assignment and/or setting:
  #
  # For example, assuming that there is an accessor defined as <tt>d</tt>:
  #
  #   assign_with( '@a'=>1, '@@b'=>2, '$c'=>3, 'd'=>4 )
  #   @a   #=> 1
  #   @@b  #=> 2
  #   $c   #=> 3
  #   d    #=> 4
  #
  # Note that while the global variable is strictly unnecessary,
  # it works for completeness sake.
  #
  #--
  # TODO This proabably should be called instance_assign_with given
  # it's nature. Maybe consider that in the future.
  #
  # TODO Maybe assign_with should only handle instance vars, like
  # assign from does. Then another method could do what this now does.
  # Say instance_assign could be extended to handle a hash.
  #
  # TODO Make a little more flexiable to allow any hash-like object.
  #++

  def assign_with(*args)
    harg = args.last.is_a?(Hash) ? args.pop : {}

    unless args.empty?
      # if not assoc array, eg. [ [], [], ... ]
      # preserves order of opertation
      unless args[0].is_a?(Array)
        i = 0; a = []
        while i < args.size
          a << [ args[i], args[i+1] ]
          i += 2
        end
        args = a
      end
    end

    args.each do |k,v|
      instance_assign( k, v )
    end

    harg.each do |k,v|
      instance_assign( k, v )
    end

    return self
  end

end


#  _____         _
# |_   _|__  ___| |_
#   | |/ _ \/ __| __|
#   | |  __/\__ \ |_
#   |_|\___||___/\__|
#
=begin test

  require 'test/unit'

  class TCKernel < Test::Unit::TestCase

    def test_assign_with
      ahash = { "z"=>0, "@a"=>1, "@b"=>2 } #, "@@a"=>3 }
      assign_with( ahash )
      assert_equal( 0, @z )
      assert_equal( 1, @a )
      assert_equal( 2, @b )
      #assert_equal( 3, @@a )
    end

  end

=end
