require 'test/unit'

module Borges;end
require 'Borges/Callback/Callback'
require 'Borges/Callback/ActionCallback'
require 'Borges/Callback/DispatchCallback'
require 'Borges/Callback/ValueCallback'
require 'Borges/Callback/CallbackStore'

class CallbackStoreTest < Test::Unit::TestCase

  def setup
    @store = Borges::CallbackStore.new
  end

  def test_action
    @store.register_action_callback do "action" end
    req = Object.new
    class << req
      def fields; ["0"]; end
    end

    assert_equal "action", @store.process_request(req),
                 "Action gets called by #process_request"
  end

  def test_register_action_callback
    key = @store.register_action_callback do
      "action callback"
    end

    assert_equal 0, key, "Key has an index"
    assert_equal "action callback",
                 @store.evaluate(key.to_i, nil).call,
                 "Callback is stored at key"
  end

  def test_register_callback
    key = @store.register_callback do
      "callback"
    end

    assert_equal 0, key, "Key has an index"
    assert_equal "callback",
                 @store.evaluate(key.to_i, nil),
                 "Callback is stored at key"
  end

  # HACK: this test is not right
  def test_register_dispatch_callback
    key = @store.register_dispatch_callback

    assert_equal 0, key, "Key has an index"
    assert_raises(Borges::CallbackNotFound, "Just a placeholder") do
      @store.evaluate(key.to_i + 1, nil)
    end
  end

  def test_store
    callback_one = Borges::ActionCallback.new do "callback one" end
    callback_two = Borges::ActionCallback.new do "callback two" end

    key_one = @store.store callback_one
    key_two = @store.store callback_two

    assert_equal 0, key_one, "Keys have unique values"
    assert_equal 1, key_two, "Keys have unique values"

    assert_equal "callback one",
                 @store.evaluate(key_one.to_i, nil).call,
                 "Callback can be fetched by key"
    assert_equal "callback two",
                 @store.evaluate(key_two.to_i, nil).call,
                 "Callback can be fetched by key"
  end

  def test_value_for_field_nil
    assert_equal '', @store.value_for_field(nil),
                 "Nil converts to empty string"
  end

  def test_value_for_field_empty
    assert_equal '', @store.value_for_field([]),
                 "Empty Array converts to empty string"
  end

  def test_value_for_field_one_value
    assert_equal 'value', @store.value_for_field(["value"]),
                 "Value is pulled from Array"
  end

  def test_value_for_field_two_values
    assert_equal 'value one',
                 @store.value_for_field(["value one", "value two"]),
                 "First value is pulled from Array"
  end

  def test_value_for_field_string
    assert_equal 'value',
                 @store.value_for_field("value"),
                 "String passed through unmodified"
  end

  def test_sort_request_empty
    assert_equal [], @store.sort_request(nil),
                 "Valid response with no fields"
  end

  def test_sort_request
    input = [
      ["4", "value four"],
      ["2", "value two"],
      ["3", "value three"],
      ["1", "value one"],
    ]

    expected = [
      [1, "value one"],
      [2, "value two"],
      [3, "value three"],
      [4, "value four"],
    ]

    assert_equal expected, @store.sort_request(input), "Sort fields by name"
  end

  # TODO: test dispatch_callback
  def test_process_request
    x = nil
    y = nil
    @store.register_action_callback do "action" end
    @store.register_callback do x = "value one" end
    @store.register_callback do |v| y = v end
    req = Object.new
    class << req
      def fields; {"0" => "", "1" => "", "2" => "value two"}; end
    end

    z = @store.process_request(req)
    assert_equal "value one", x, "Value set from callback"
    assert_equal "value two", y, "Value set from request string"
    assert_equal "action", z, "Value retrieved from action"
  end

end # class CallbackStoreTest
