require "test/unit"
require "test/unit/ui/console/testrunner"

include StarEngine

class ColorTest < Test::Unit::TestCase
  
  def test_color
    c1 = Color.new 1, 2, 3, 4
    c2 = Color.new 5, 6, 7

    assert_equal 1, c1.red
    assert_equal 2, c1.green
    assert_equal 3, c1.blue
    assert_equal 4, c1.alpha
    assert_equal 255, c2.alpha

    assert c1 == Color.new(1, 2, 3, 4)
    assert c1.eql?(Color.new(1, 2, 3, 4))
    assert_equal c1.hash, Color.new(1, 2, 3, 4).hash
  end
  
end

class ToneTest < Test::Unit::TestCase

  def test_tone
    t1 = Tone.new 1, 2, 3, 4
    t2 = Tone.new 5, 6, 7

    assert_equal 1, t1.red
    assert_equal 2, t1.green
    assert_equal 3, t1.blue
    assert_equal 4, t1.saturation
    assert_equal 255, t2.saturation

    assert t1 == Tone.new(1, 2, 3, 4)
    assert t1.eql?(Tone.new(1, 2, 3, 4))
    assert_equal t1.hash, Tone.new(1, 2, 3, 4).hash
  end
  
end

class FontTest < Test::Unit::TestCase
  
  def test_exist
    assert_equal true,  Font.exist?("Arial")
    assert_equal true,  Font.exist?("ＭＳ ゴシック")
    assert_equal false, Font.exist?("存在しないフォント")
    assert_equal true,  Font.exist?("Resources/Fonts/04B_11__")
    assert_equal true,  Font.exist?("Resources/Fonts/04B_11__.TTF")
    assert_equal false, Font.exist?("Resources/Fonts/04B_12__")
    assert_equal false, Font.exist?("Hoge/Resources/Fonts/04B_11__")
    # ファイルの中身は精査しない
    assert_equal true,  Font.exist?("Resources/Images/Ruby.png")
  end
  
  def test_new
    font = Font.new "ＭＳ ゴシック", 12
    assert_equal "ＭＳ ゴシック", font.name
    assert_equal 12, font.size
    assert_equal false, font.bold?
    assert_equal false, font.italic?
    assert_equal [6, 12],  font.get_size("A")
    assert_equal [78, 12], font.get_size("Hello, World!")
    assert_equal [60, 12], font.get_size("こんにちは")
    assert_equal [30, 12], font.get_size("aaa&a")
    assert_equal [30, 12], font.get_size("aaa\na")
    assert_equal [30, 12], font.get_size("aa\r\na")
    assert_equal [30, 12], font.get_size("aaa\ta")
    
    font = Font.new "Arial", 10.5, :bold => true, :italic => true
    assert_equal "Arial", font.name
    assert_equal 10.5, font.size
    assert_equal true, font.bold?
    assert_equal true, font.italic?
  end
  
  def test_new2
    font = Font.new "Resources/Fonts/04B_11__", 12
    assert_equal "04b11", font.name
    assert_equal 12, font.size
    assert_equal false, font.bold?
    assert_equal false, font.italic?
    
    font = Font.new "Resources/Fonts/04B_11__.TTF", 12
    assert_equal "04b11", font.name
  end
  
  def test_new3
    assert_raise Errno::ENOENT do
      Font.new "Resources/hoge", 12
    end
    assert_raise Errno::ENOENT do
      Font.new "InvalidPath/Fonts/04B_11__", 12
    end
    assert_raise StarEngineError do
      Font.new "Resources/Images/Ruby.png", 12
    end
  end
  
end

class TextureTest < Test::Unit::TestCase
  
  def setup
    @font = Font.new "ＭＳ ゴシック", 12
  end
  
  def test_new
    texture = Texture.new 123, 456
    assert_equal [123, 456], texture.size
    assert_equal 123,        texture.width
    assert_equal 456,        texture.height
  end
  
  def test_load
    texture = Texture.load "Resources/Images/Ruby.png"
    assert_equal [50, 35], texture.size
    assert_equal 50,       texture.width
    assert_equal 35,       texture.height
    
    assert_raise Errno::ENOENT do
      Texture.load "InvalidPath/hoge.png"
    end
    
    assert_raise Errno::ENOENT do
      Texture.load "Resources/Images/NotExistedImage.png"
    end
    
    assert_not_nil Texture.load("Resources/Images/Ruby")
    assert_not_nil Texture.load("Resources/Images/RubyCompressed.pngx")
    assert_not_nil Texture.load("Resources/Images/RubyCompressed")
    assert_not_nil Texture.load("Resources/Images/RubyPng")
    
    # not image
    assert_raise StarEngineError do
      Texture.load("Resources/Images/NotImage")
    end
  end
  
  def test_clone
    texture = Texture.load "Resources/Images/Ruby.png"
    texture2 = texture.clone
    assert_equal texture.size, texture2.size
    texture.freeze
    texture3 = texture.clone
    assert_equal true, texture3.frozen?
  end
  
  def test_dup
    texture = Texture.load "Resources/Images/Ruby.png"
    texture2 = texture.dup
    assert_equal texture.size, texture2.size
    texture.freeze
    texture3 = texture.dup
    assert_equal false, texture3.frozen?
  end
  
  def test_dispose
    texture = Texture.load "Resources/Images/Ruby.png"
    assert_equal false, texture.disposed?
    texture.dispose
    assert_equal true, texture.disposed?
    assert_raise StarEngineError do
      texture.dispose
    end
    assert_raise StarEngineError do
      texture.change_hue 10
    end
  end
  
  def test_get_and_set_pixel
    texture = Texture.new 3, 3
    texture.height.times do |y|
      texture.width.times do |x|
        assert_equal Color.new(0,0,0,0), texture.get_pixel(x,y)
      end
    end
    
    assert_raise IndexError do
      texture.get_pixel 3, 2
    end
    
    texture.set_pixel 0, 1, Color.new(31, 41, 59, 26)
    texture.set_pixel 1, 2, Color.new(53, 58, 97, 92)
    texture.set_pixel 2, 0, Color.new(65, 35, 89, 79)
    assert_equal Color.new(31, 41, 59, 26), texture.get_pixel(0, 1);
    assert_equal Color.new(53, 58, 97, 92), texture.get_pixel(1, 2);
    assert_equal Color.new(65, 35, 89, 79), texture.get_pixel(2, 0);
    
    assert_raise IndexError do
      texture.get_pixel 2, 3
    end
  end
  
  def test_set_pixel_frozen
    texture = Texture.new 3, 3
    texture.freeze
    assert_raise TypeError do
      texture.set_pixel 0, 1, Color.new(31, 41, 59, 26)
    end
  end
  
  def test_set_pixel_disposed
    texture = Texture.new 3, 3
    texture.dispose
    assert_raise StarEngineError do
      texture.set_pixel 0, 1, Color.new(31, 41, 59, 26)
    end
  end
  
  def test_change_hue
    texture = Texture.load "Resources/Images/Ruby.png"
    orig_texture = texture.clone
    (-10..369).each do |d|
      texture = orig_texture.clone
      texture.change_hue d
      texture.dispose
    end
    texture = orig_texture
    texture.freeze
    assert_raise TypeError do
      texture.change_hue 10
    end
  end
  
  def test_clear
    texture = Texture.load "Resources/Images/Ruby.png"
    texture.clear
    texture.height.times do |y|
      texture.width.times do |x|
        assert_equal Color.new(0,0,0,0), texture.get_pixel(x,y)
      end
    end
  end
  
  def test_clear_frozen
    texture = Texture.load "Resources/Images/Ruby.png"
    texture.freeze
    assert_raise TypeError do
      texture.clear
    end
  end
  
  def test_clear_dispose
    texture = Texture.load "Resources/Images/Ruby.png"
    texture.dispose
    assert_raise StarEngineError do
      texture.clear
    end
  end
  
  def test_fill
    texture = Texture.load "Resources/Images/Ruby.png"
    texture.fill Color.new(12, 34, 56, 78)
    texture.height.times do |y|
      texture.width.times do |x|
        assert_equal Color.new(12, 34, 56, 78), texture.get_pixel(x,y)
      end
    end
  end
  
  def test_fill_frozen
    texture = Texture.load "Resources/Images/Ruby.png"
    texture.freeze
    assert_raise TypeError do
      texture.fill Color.new(12, 34, 56, 78)
    end
  end
  
  def test_fill_dispose
    texture = Texture.load "Resources/Images/Ruby.png"
    texture.dispose
    assert_raise StarEngineError do
      texture.fill Color.new(12, 34, 56, 78)
    end
  end
  
  def test_fill_rect
    texture = Texture.load "Resources/Images/Ruby.png"
    orig_texture = texture.clone
    texture.fill_rect 10, 11, 12, 13, Color.new(12, 34, 56, 78)
    texture.height.times do |y|
      texture.width.times do |x|
        if 10 <= x and 11 <= y and x < 22 and y < 24
          assert_equal Color.new(12, 34, 56, 78), texture.get_pixel(x, y)
        else
          assert_equal orig_texture.get_pixel(x, y), texture.get_pixel(x, y)
        end
      end
    end
  end
  
  def test_fill_rect_frozen
    texture = Texture.load "Resources/Images/Ruby.png"
    texture.freeze
    assert_raise TypeError do
      texture.fill_rect 10, 10, 15, 15, Color.new(12, 34, 56, 78)
    end
  end
  
  def test_fill_rect_dispose
    texture = Texture.load "Resources/Images/Ruby.png"
    texture.dispose
    assert_raise StarEngineError do
      texture.fill_rect 10, 10, 15, 15, Color.new(12, 34, 56, 78)
    end
  end
  
  def test_render_text
    texture = Texture.new 100, 100
    %W(A Hello,\ World aaa&a aaa\na aa\r\na aaa\ta).each do |str|
      texture.render_text str, 12, 34, @font, Color.new(12,34,56,78)
    end
  end
  
  def test_render_text_hello
    texture_actual = Texture.new 66, 18
    texture_actual.fill Color.new(0, 0, 0)
    texture_actual.render_text "こんにちは", 3, 3, @font, Color.new(255, 255, 255)
    texture_expected = Texture.load "Resources/Images/TestRenderText/Hello2"
    
    18.times do |y|
      66.times do |x|
        assert_equal texture_expected.get_pixel(x, y), texture_actual.get_pixel(x, y)
      end
    end
  end
  
  def test_render_text_frozen
    texture = Texture.new 100, 100
    texture.freeze
    assert_raise TypeError do
      texture.render_text "hoge", 12, 34, @font, Color.new(12,34,56,78)
    end
  end
  
  def test_render_text_dispose
    texture = Texture.new 100, 100
    texture.dispose
    assert_raise StarEngineError do
      texture.render_text "hoge", 12, 34, @font, Color.new(12,34,56,78)
    end
  end
  
  def test_render_texture
    texture1 = Texture.new 100, 100
    texture2 = Texture.new 100, 100
    texture1.render_texture texture2, 0, 0
    assert_raise StarEngineError do
      texture1.render_texture texture2, 0, 0, :scalee_x => 2, :scale_y => 3
    end
    texture2.dispose
    assert_raise StarEngineError do
      texture1.render_texture texture2, 0, 0
    end
  end
  
  def test_render_texture_frozen
    texture1 = Texture.new 100, 100
    texture1.freeze
    texture2 = Texture.new 100, 100
    assert_raise TypeError do
      texture1.render_texture texture2, 0, 0
    end
  end
  
  def test_render_texture_frozen
    texture1 = Texture.new 100, 100
    texture1.dispose
    texture2 = Texture.new 100, 100
    assert_raise StarEngineError do
      texture1.render_texture texture2, 0, 0
    end
  end
  
  def test_render_texture_self
    texture = Texture.new 100, 100
    texture.render_texture texture, 0, 0
  end

end

class GameTest < Test::Unit::TestCase

  def test_game
    Game.terminate if Game.running?
    assert_equal false, Game.running?
    Game.title = "hoge1"
    assert_equal "hoge1", Game.title
    Game.fps = 31
    assert_equal 31, Game.fps
    Game.run do
      assert_equal true, Game.running?
      Game.title = "hoge2"
      assert_equal "hoge2", Game.title
      Game.fps = 32
      assert_equal 32, Game.fps
      assert_raise StarEngineError do
        Game.run {}
      end
      Game.terminate
      assert_equal true, Game.running?
    end
    assert_equal false, Game.running?
    Game.title = "hoge3"
    assert_equal "hoge3", Game.title
    Game.fps = 33
    assert_equal 33, Game.fps
  end
  
end

class ScreenTest < Test::Unit::TestCase
  
  def test_screen
    assert_equal 320, Screen.width
    assert_equal 240, Screen.height
    assert_equal [320, 240], Screen.size
  end
  
  def test_save_screenshot
    assert ! FileTest.exist?("screenshot.png")
    i = 0
    Game.run do
      case i
      when 0
        Screen.save_screenshot "screenshot.png"
        assert ! FileTest.exist?("screenshot.png")
      when 1
        #Thread.new do
        #  sleep(0.1) until FileTest.exist?("screenshot.png")
        #end.join(5)
        assert FileTest.exist?("screenshot.png")
        Game.terminate
      end
      i += 1
    end
    assert FileTest.exist?("screenshot.png")
    File.delete "screenshot.png"
  end
  
  def test_offscreen
    assert_kind_of Texture, Screen.offscreen
    assert_equal Screen.width, Screen.offscreen.width
    assert_equal Screen.height, Screen.offscreen.height
  end
  
end

class AudioTest < Test::Unit::TestCase
  
  def test_play_bgm
    assert_raise Errno::ENOENT do
      Audio.play_bgm "Resources/hoge"
    end
    assert_raise Errno::ENOENT do
      Audio.play_bgm "InvalidPath/hoge/huga"
    end
    assert_raise StarEngineError do
      Audio.play_bgm "Resources/Images/Ruby.png"
    end
  end
  
  def test_play_se
    assert_raise Errno::ENOENT do
      Audio.play_se "Resources/hoge"
    end
    assert_raise Errno::ENOENT do
      Audio.play_se "InvalidPath/hoge/huga"
    end
    assert_raise StarEngineError do
      Audio.play_se "Resources/Images/Ruby.png"
    end
  end
  
  def test_play_se
  end
  
  def test_bgm_volume
    assert_equal 255, Audio.bgm_volume
    Audio.bgm_volume = 128
    assert_equal 128, Audio.bgm_volume
  end
  
end

suite = Test::Unit::TestSuite.new "Star Engine Test"
self.class.constants.select do |const_name|
  const_name =~ /.Test$/
end.map do |const_name|
  self.class.const_get(const_name)
end.select do |const|
  const < Test::Unit::TestCase
end.each do |test_case|
  suite << test_case.suite
end
Test::Unit::UI::Console::TestRunner.new(suite).start
StarEngine::activate_console
