 defmodule HighScoreTest do
   use ExUnit.Case
 
-  # Trivia: Scores are based on lines added to the elixir-lang/elixir
-  # github repository as of Apr 27, 2020.
-  @chris {"Chris McCord", 0}
-  @jose {"José Valim", 486_373}
-  @dave {"Dave Thomas", 2_374}
-  @sasa {"Saša Jurić", 762}
+  # Trivia: Scores used in this test suite are based on lines of code
+  # added to the elixir-lang/elixir github repository as of Apr 27, 2020.
 
   # @tag :pending
   test "new/1 result in empty score map" do


    @tag :pending
    test "score map with one entry gives one result" do
      {jose, score} = @jose
      scores_by_player =
        HighScore.new()
        |> HighScore.add_player(jose)
        |> HighScore.update_score(jose, score)
        |> HighScore.order_by_players()

      assert scores_by_player == [@jose]
    end

    @tag :pending
    test "score map with two entries gives ordered result" do
      {jose, jose_score} = @jose
      {dave, dave_score} = @dave
      scores_by_player =
        HighScore.new()
        |> HighScore.add_player(jose, jose_score)
        |> HighScore.add_player(dave, dave_score)
        |> HighScore.order_by_players()

      assert scores_by_player == [@dave, @jose]
    end

    @tag :pending
    test "score map with multiple entries gives ordered result" do
      {jose, jose_score} = @jose
      {dave, dave_score} = @dave
      {chris, chris_score} = @chris
      {sasa, sasa_score} = @sasa

      scores_by_player =
        HighScore.new()
        |> HighScore.add_player(jose, jose_score)
        |> HighScore.add_player(dave, dave_score)
        |> HighScore.add_player(chris, chris_score)
        |> HighScore.add_player(sasa, sasa_score)
        |> HighScore.order_by_players()

      assert scores_by_player == [@chris, @dave, @jose, @sasa]
    end
  end


  describe "add_player/2" do
    @tag :pending
    test "add player without score to empty score map" do
      scores = HighScore.new()

      assert HighScore.add_player(scores, "José Valim") == %{"José Valim" => 0}
    end

    @tag :pending
    test "add two players without score to empty map" do
      scores =
        HighScore.new()
        |> HighScore.add_player("José Valim")
        |> HighScore.add_player("Chris McCord")

      assert scores == %{"Chris McCord" => 0, "José Valim" => 0}
    end

    @tag :pending
    test "add player with score to empty score map" do
      scores =
        HighScore.new()
        |> HighScore.add_player("José Valim", 486_373)

      assert scores == %{"José Valim" => 486_373}
    end

    @tag :pending
    test "add players with scores to empty score map" do
      scores =
        HighScore.new()
        |> HighScore.add_player("José Valim", 486_373)
        |> HighScore.add_player("Dave Thomas", 2_374)

      assert scores == %{"José Valim" => 486_373, "Dave Thomas" => 2_374}
    end
  end

  describe "remove_player/2" do
    @tag :pending
    test "remove from empty score map results in empty score map" do
      scores =
        HighScore.new()
        |> HighScore.remove_player("José Valim")

      assert scores == %{}
    end

    @tag :pending
    test "remove player after adding results in empty score map" do
      map =
        HighScore.new()
        |> HighScore.add_player("José Valim")
        |> HighScore.remove_player("José Valim")

      assert map == %{}
    end

    @tag :pending
    test "remove first player after adding two results in map with remaining player" do
      scores =
        HighScore.new()
        |> HighScore.add_player("José Valim")
        |> HighScore.add_player("Chris McCord")
        |> HighScore.remove_player("José Valim")

      assert scores == %{"Chris McCord" => 0}
    end

    @tag :pending
    test "remove second player after adding two results in map with remaining player" do
      scores =
        HighScore.new()
        |> HighScore.add_player("José Valim")
        |> HighScore.add_player("Chris McCord")
        |> HighScore.remove_player("Chris McCord")

      assert scores == %{"José Valim" => 0}
    end
  end

  describe "reset_score/2" do
    @tag :pending
    test "resetting score for non-existent player sets player score to 0" do
      scores =
        HighScore.new()
        |> HighScore.reset_score("José Valim")

      assert scores == %{"José Valim" => 0}
    end

    @tag :pending
    test "resetting score for existing player sets previous player score to 0" do
      scores =
        HighScore.new()
        |> HighScore.add_player("José Valim")
        |> HighScore.update_score("José Valim", 486_373)
        |> HighScore.reset_score("José Valim")

      assert scores == %{"José Valim" => 0}
    end
  end

  describe "update_score/3" do
    @tag :pending
    test "update score for non existent player initializes value" do
      scores =
        HighScore.new()
        |> HighScore.update_score("José Valim", 486_373)

      assert scores == %{"José Valim" => 486_373}
    end

    @tag :pending
    test "update score for existing player adds score to previous" do
      scores =
        HighScore.new()
        |> HighScore.add_player("José Valim")
        |> HighScore.update_score("José Valim", 486_373)

      assert scores == %{"José Valim" => 486_373}
    end

    @tag :pending
    test "update score for existing player with non-zero score adds score to previous" do
      scores =
        HighScore.new()
        |> HighScore.add_player("José Valim")
        |> HighScore.update_score("José Valim", 1)
        |> HighScore.update_score("José Valim", 486_373)

      assert scores == %{"José Valim" => 486_374}
    end
  end

