From 1f5638539ff220e4e1d2f918c76e13a0968517ed Mon Sep 17 00:00:00 2001
From: poixen <githubpoixen@gmail.com>
Date: Thu, 19 Nov 2015 09:53:52 +0100
Subject: [PATCH] Class Overhaul
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

+ added javadoc
+ added final to method variables that should not be mutated
+ Mana can no longer be initialised with minus values
+ added null assertions
+ renamed ‘addXXX’ to ‘increaseXXX’. Add implies that you are able to
add variable amounts.
+ subtraction can no longer allow minus values.
+ removed unused state
+ refactored classes use renamed/removed mana calls
+ added comment to contains(), needs to be looked into?
+ Added validation to setting of mana. Can no longer be set to minus
values. Will log if an attempt is made
+Added comment to static mana, this is unsafe.
---
 .../mage/sets/dragonsmaze/PlasmCapture.java   |  10 +-
 .../sets/dragonsoftarkir/SarkhanUnbroken.java |  10 +-
 .../src/mage/sets/eventide/BloomTender.java   |  10 +-
 .../mage/sets/fifthdawn/DawnsReflection.java  |  10 +-
 .../mage/sets/futuresight/CoalitionRelic.java |  10 +-
 .../heroesvsmonsters/OrcishLumberjack.java    |   4 +-
 .../sets/journeyintonyx/MarketFestival.java   |  10 +-
 .../mage/sets/legions/GoblinClearcutter.java  |  11 +-
 .../SasayaOrochiAscendant.java                |  12 +-
 .../mage/sets/shadowmoor/ManaforgeCinder.java |   4 +-
 .../mage/sets/theros/XenagosTheReveler.java   |   4 +-
 .../java/org/mage/test/mana/ManaTest.java     | 650 ++++++++++++++++++
 Mage/src/mage/Mana.java                       | 475 +++++++++----
 .../abilities/costs/mana/ManaCostImpl.java    |  22 +-
 .../effects/common/DynamicManaEffect.java     |  10 +-
 .../CommanderManaReplacementEffect.java       |  10 +-
 16 files changed, 1070 insertions(+), 192 deletions(-)
 create mode 100644 Mage.Tests/src/test/java/org/mage/test/mana/ManaTest.java

diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/PlasmCapture.java b/Mage.Sets/src/mage/sets/dragonsmaze/PlasmCapture.java
index cf82ebbf9e..ae7f5f64f0 100644
--- a/Mage.Sets/src/mage/sets/dragonsmaze/PlasmCapture.java
+++ b/Mage.Sets/src/mage/sets/dragonsmaze/PlasmCapture.java
@@ -141,15 +141,15 @@ class PlasmCaptureManaEffect extends ManaEffect {
                 }
 
                 if (choiceColor.getColor().isBlack()) {
-                    mana.addBlack();
+                    mana.increaseBlack();
                 } else if (choiceColor.getColor().isBlue()) {
-                    mana.addBlue();
+                    mana.increaseBlue();
                 } else if (choiceColor.getColor().isRed()) {
-                    mana.addRed();
+                    mana.increaseRed();
                 } else if (choiceColor.getColor().isGreen()) {
-                    mana.addGreen();
+                    mana.increaseGreen();
                 } else if (choiceColor.getColor().isWhite()) {
-                    mana.addWhite();
+                    mana.increaseWhite();
                 }
             }
 
diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/SarkhanUnbroken.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/SarkhanUnbroken.java
index ccd28a1c47..daf2b76935 100644
--- a/Mage.Sets/src/mage/sets/dragonsoftarkir/SarkhanUnbroken.java
+++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/SarkhanUnbroken.java
@@ -132,19 +132,19 @@ class SarkhanUnbrokenAbility1 extends OneShotEffect {
 
             switch (manaChoice.getChoice()) {
                 case "White":
-                    mana.addWhite();
+                    mana.increaseWhite();
                     break;
                 case "Blue":
-                    mana.addBlue();
+                    mana.increaseBlue();
                     break;
                 case "Black":
-                    mana.addBlack();
+                    mana.increaseBlack();
                     break;
                 case "Red":
-                    mana.addRed();
+                    mana.increaseRed();
                     break;
                 case "Green":
-                    mana.addGreen();
+                    mana.increaseGreen();
                     break;
             }
 
diff --git a/Mage.Sets/src/mage/sets/eventide/BloomTender.java b/Mage.Sets/src/mage/sets/eventide/BloomTender.java
index f4544ddc23..ecadab68f7 100644
--- a/Mage.Sets/src/mage/sets/eventide/BloomTender.java
+++ b/Mage.Sets/src/mage/sets/eventide/BloomTender.java
@@ -107,19 +107,19 @@ class BloomTenderEffect extends ManaEffect {
             Mana mana = new Mana();
             for (Permanent permanent : game.getBattlefield().getAllActivePermanents(controller.getId())) {
                 if (mana.getBlack() == 0 && permanent.getColor(game).isBlack()) {
-                    mana.addBlack();
+                    mana.increaseBlack();
                 }
                 if (mana.getBlue() == 0 && permanent.getColor(game).isBlue()) {
-                    mana.addBlue();
+                    mana.increaseBlue();
                 }
                 if (mana.getRed() == 0 && permanent.getColor(game).isRed()) {
-                    mana.addRed();
+                    mana.increaseRed();
                 }
                 if (mana.getGreen() == 0 && permanent.getColor(game).isGreen()) {
-                    mana.addGreen();
+                    mana.increaseGreen();
                 }
                 if (mana.getWhite() == 0 && permanent.getColor(game).isWhite()) {
-                    mana.addWhite();
+                    mana.increaseWhite();
                 }
             }
             return mana;
diff --git a/Mage.Sets/src/mage/sets/fifthdawn/DawnsReflection.java b/Mage.Sets/src/mage/sets/fifthdawn/DawnsReflection.java
index 417381b270..e511ed5586 100644
--- a/Mage.Sets/src/mage/sets/fifthdawn/DawnsReflection.java
+++ b/Mage.Sets/src/mage/sets/fifthdawn/DawnsReflection.java
@@ -142,15 +142,15 @@ class DawnsReflectionManaEffect extends ManaEffect {
                 }
 
                 if (choiceColor.getColor().isBlack()) {
-                    mana.addBlack();
+                    mana.increaseBlack();
                 } else if (choiceColor.getColor().isBlue()) {
-                    mana.addBlue();
+                    mana.increaseBlue();
                 } else if (choiceColor.getColor().isRed()) {
-                    mana.addRed();
+                    mana.increaseRed();
                 } else if (choiceColor.getColor().isGreen()) {
-                    mana.addGreen();
+                    mana.increaseGreen();
                 } else if (choiceColor.getColor().isWhite()) {
-                    mana.addWhite();
+                    mana.increaseWhite();
                 }
             }
 
diff --git a/Mage.Sets/src/mage/sets/futuresight/CoalitionRelic.java b/Mage.Sets/src/mage/sets/futuresight/CoalitionRelic.java
index 1c7ec71523..3c2b480ecb 100644
--- a/Mage.Sets/src/mage/sets/futuresight/CoalitionRelic.java
+++ b/Mage.Sets/src/mage/sets/futuresight/CoalitionRelic.java
@@ -109,15 +109,15 @@ class CoalitionRelicEffect extends OneShotEffect {
                     player.choose(outcome, choice, game);
                 }
                 if (choice.getColor().isBlack()) {
-                    mana.addBlack();
+                    mana.increaseBlack();
                 } else if (choice.getColor().isBlue()) {
-                    mana.addBlue();
+                    mana.increaseBlue();
                 } else if (choice.getColor().isRed()) {
-                    mana.addRed();
+                    mana.increaseRed();
                 } else if (choice.getColor().isGreen()) {
-                    mana.addGreen();
+                    mana.increaseGreen();
                 } else if (choice.getColor().isWhite()) {
-                    mana.addWhite();
+                    mana.increaseWhite();
                 }
                 choice.clearChoice();
             }
diff --git a/Mage.Sets/src/mage/sets/heroesvsmonsters/OrcishLumberjack.java b/Mage.Sets/src/mage/sets/heroesvsmonsters/OrcishLumberjack.java
index 93277aa22f..3a06eafc05 100644
--- a/Mage.Sets/src/mage/sets/heroesvsmonsters/OrcishLumberjack.java
+++ b/Mage.Sets/src/mage/sets/heroesvsmonsters/OrcishLumberjack.java
@@ -123,10 +123,10 @@ class OrcishLumberjackManaEffect extends ManaEffect {
                 }
                 switch (manaChoice.getChoice()) {
                     case "Green":
-                        mana.addGreen();
+                        mana.increaseGreen();
                         break;
                     case "Red":
-                        mana.addRed();
+                        mana.increaseRed();
                         break;
                 }
                 
diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/MarketFestival.java b/Mage.Sets/src/mage/sets/journeyintonyx/MarketFestival.java
index affa7e15e9..daa67c1397 100644
--- a/Mage.Sets/src/mage/sets/journeyintonyx/MarketFestival.java
+++ b/Mage.Sets/src/mage/sets/journeyintonyx/MarketFestival.java
@@ -154,15 +154,15 @@ class MarketFestivalManaEffect extends ManaEffect {
                 }
 
                 if (choiceColor.getColor().isBlack()) {
-                    mana.addBlack();
+                    mana.increaseBlack();
                 } else if (choiceColor.getColor().isBlue()) {
-                    mana.addBlue();
+                    mana.increaseBlue();
                 } else if (choiceColor.getColor().isRed()) {
-                    mana.addRed();
+                    mana.increaseRed();
                 } else if (choiceColor.getColor().isGreen()) {
-                    mana.addGreen();
+                    mana.increaseGreen();
                 } else if (choiceColor.getColor().isWhite()) {
-                    mana.addWhite();
+                    mana.increaseWhite();
                 }
             }
             checkToFirePossibleEvents(mana, game, source);
diff --git a/Mage.Sets/src/mage/sets/legions/GoblinClearcutter.java b/Mage.Sets/src/mage/sets/legions/GoblinClearcutter.java
index 20a5279fbb..bce8de7308 100644
--- a/Mage.Sets/src/mage/sets/legions/GoblinClearcutter.java
+++ b/Mage.Sets/src/mage/sets/legions/GoblinClearcutter.java
@@ -32,15 +32,11 @@ import java.util.Set;
 import java.util.UUID;
 import mage.MageInt;
 import mage.Mana;
-import mage.ObjectColor;
 import mage.abilities.Ability;
 import mage.abilities.common.SimpleActivatedAbility;
 import mage.abilities.costs.common.SacrificeTargetCost;
 import mage.abilities.costs.common.TapSourceCost;
-import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.dynamicvalue.common.ManacostVariableValue;
 import mage.abilities.effects.OneShotEffect;
-import mage.abilities.effects.common.DamageTargetEffect;
 import mage.cards.CardImpl;
 import mage.choices.Choice;
 import mage.choices.ChoiceImpl;
@@ -48,14 +44,11 @@ import mage.constants.CardType;
 import mage.constants.Outcome;
 import mage.constants.Rarity;
 import mage.constants.Zone;
-import mage.filter.common.FilterControlledCreaturePermanent;
 import mage.filter.common.FilterControlledPermanent;
-import mage.filter.predicate.mageobject.ColorPredicate;
 import mage.filter.predicate.mageobject.SubtypePredicate;
 import mage.game.Game;
 import mage.players.Player;
 import mage.target.common.TargetControlledPermanent;
-import mage.target.common.TargetCreatureOrPlayer;
 
 /**
  * @author BursegSardaukar
@@ -132,10 +125,10 @@ class GoblinClearCutterEffect extends OneShotEffect {
                 }
                 switch (manaChoice.getChoice()) {
                     case "Green":
-                        mana.addGreen();
+                        mana.increaseGreen();
                         break;
                     case "Red":
-                        mana.addRed();
+                        mana.increaseRed();
                         break;
                 }
                 player.getManaPool().addMana(mana, game, source);
diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/SasayaOrochiAscendant.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/SasayaOrochiAscendant.java
index 3bc2a38c37..3804d61c11 100644
--- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/SasayaOrochiAscendant.java
+++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/SasayaOrochiAscendant.java
@@ -202,22 +202,22 @@ class SasayasEssenceManaEffectEffect extends ManaEffect {
                         }
                         switch (choice.getChoice()) {
                             case "Black":
-                                newMana.addBlack();
+                                newMana.increaseBlack();
                                 break;
                             case "Blue":
-                                newMana.addBlue();
+                                newMana.increaseBlue();
                                 break;
                             case "Red":
-                                newMana.addRed();
+                                newMana.increaseRed();
                                 break;
                             case "Green":
-                                newMana.addGreen();
+                                newMana.increaseGreen();
                                 break;
                             case "White":
-                                newMana.addWhite();
+                                newMana.increaseWhite();
                                 break;
                             case "Colorless":
-                                newMana.addColorless();
+                                newMana.increaseColorless();
                                 break;
                         }
                     }
diff --git a/Mage.Sets/src/mage/sets/shadowmoor/ManaforgeCinder.java b/Mage.Sets/src/mage/sets/shadowmoor/ManaforgeCinder.java
index c650a49008..5501ab9ade 100644
--- a/Mage.Sets/src/mage/sets/shadowmoor/ManaforgeCinder.java
+++ b/Mage.Sets/src/mage/sets/shadowmoor/ManaforgeCinder.java
@@ -114,10 +114,10 @@ class ManaforgeCinderManaEffect extends OneShotEffect {
             }
             switch (manaChoice.getChoice()) {
                 case "Black":
-                    mana.addBlack();
+                    mana.increaseBlack();
                     break;
                 case "Red":
-                    mana.addRed();
+                    mana.increaseRed();
                     break;
             }
             controller.getManaPool().addMana(mana, game, source);
diff --git a/Mage.Sets/src/mage/sets/theros/XenagosTheReveler.java b/Mage.Sets/src/mage/sets/theros/XenagosTheReveler.java
index 8dca641395..781fe57fdb 100644
--- a/Mage.Sets/src/mage/sets/theros/XenagosTheReveler.java
+++ b/Mage.Sets/src/mage/sets/theros/XenagosTheReveler.java
@@ -130,10 +130,10 @@ class XenagosManaEffect extends OneShotEffect {
                 }
                 switch (manaChoice.getChoice()) {
                     case "Green":
-                        mana.addGreen();
+                        mana.increaseGreen();
                         break;
                     case "Red":
-                        mana.addRed();
+                        mana.increaseRed();
                         break;
                 }
                 player.getManaPool().addMana(mana, game, source);
diff --git a/Mage.Tests/src/test/java/org/mage/test/mana/ManaTest.java b/Mage.Tests/src/test/java/org/mage/test/mana/ManaTest.java
new file mode 100644
index 0000000000..7cfa5a8857
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/mana/ManaTest.java
@@ -0,0 +1,650 @@
+package org.mage.test.mana;
+
+import mage.Mana;
+import mage.constants.ColoredManaSymbol;
+import mage.constants.ManaType;
+import mage.filter.FilterMana;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.TestCase.assertFalse;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Custom unit tests for {link Mana}.
+ *
+ * @author githubpoixen@github.com
+ */
+public class ManaTest {
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+
+    @Test
+    public void shouldNotAllowNullCopyConstructor() {
+        // given
+        expectedException.expect(NullPointerException.class);
+        expectedException.expectMessage("The passed in Mana can not be null");
+
+        // when
+        Mana nullMana = null;
+        new Mana(nullMana);
+    }
+
+
+    @Test
+    public void shouldCreateManaFromCopy() {
+        // given
+        Mana original = new Mana();
+        original.increaseBlack();
+
+        // when
+        Mana copy = new Mana(original);
+
+        // then
+        assertEquals(0, copy.getGreen());
+        assertEquals(0, copy.getRed());
+        assertEquals(1, copy.getBlack());
+        assertEquals(0, copy.getBlue());
+        assertEquals(0, copy.getWhite());
+    }
+
+
+    @Test
+    public void shouldCreateManaFromGreenColoredManaSymbol() {
+        // given
+        ColoredManaSymbol symbol = ColoredManaSymbol.G;
+
+        // when
+        Mana mana = new Mana(symbol);
+
+        // then
+        assertEquals(1, mana.getGreen());
+        assertEquals(0, mana.getRed());
+        assertEquals(0, mana.getBlack());
+        assertEquals(0, mana.getBlue());
+        assertEquals(0, mana.getWhite());
+    }
+
+
+    @Test
+    public void shouldCreateManaFromRedColoredManaSymbol() {
+        // given
+        ColoredManaSymbol symbol = ColoredManaSymbol.R;
+
+        // when
+        Mana mana = new Mana(symbol);
+
+        // then
+        assertEquals(0, mana.getGreen());
+        assertEquals(1, mana.getRed());
+        assertEquals(0, mana.getBlack());
+        assertEquals(0, mana.getBlue());
+        assertEquals(0, mana.getWhite());
+    }
+
+
+    @Test
+    public void shouldCreateManaFromBlackColoredManaSymbol() {
+        // given
+        ColoredManaSymbol symbol = ColoredManaSymbol.B;
+
+        // when
+        Mana mana = new Mana(symbol);
+
+        // then
+        assertEquals(0, mana.getGreen());
+        assertEquals(0, mana.getRed());
+        assertEquals(1, mana.getBlack());
+        assertEquals(0, mana.getBlue());
+        assertEquals(0, mana.getWhite());
+    }
+
+
+    @Test
+    public void shouldCreateManaFromBlueColoredManaSymbol() {
+        // given
+        ColoredManaSymbol symbol = ColoredManaSymbol.U;
+
+        // when
+        Mana mana = new Mana(symbol);
+
+        // then
+        assertEquals(0, mana.getGreen());
+        assertEquals(0, mana.getRed());
+        assertEquals(0, mana.getBlack());
+        assertEquals(1, mana.getBlue());
+        assertEquals(0, mana.getWhite());
+    }
+
+
+    @Test
+    public void shouldCreateManaFromWhiteColoredManaSymbol() {
+        // given
+        ColoredManaSymbol symbol = ColoredManaSymbol.W;
+
+        // when
+        Mana mana = new Mana(symbol);
+
+        // then
+        assertEquals(0, mana.getGreen());
+        assertEquals(0, mana.getRed());
+        assertEquals(0, mana.getBlack());
+        assertEquals(0, mana.getBlue());
+        assertEquals(1, mana.getWhite());
+    }
+
+
+    @Test
+    public void shouldNotCreateManaFromNullColoredManaSymbol() {
+        // given
+        ColoredManaSymbol nullSymbol = null;
+
+        expectedException.expect(NullPointerException.class);
+        expectedException.expectMessage("The passed in ColoredManaSymbol can not be null");
+
+        // when
+        new Mana(nullSymbol);
+    }
+
+
+    @Test
+    public void shouldCreateManaFromIntegers() {
+
+        // when
+        Mana mana = new Mana(1, 2, 3, 4, 5, 6, 7);
+
+        // then
+        assertEquals(1, mana.getRed());
+        assertEquals(2, mana.getGreen());
+        assertEquals(3, mana.getBlue());
+        assertEquals(4, mana.getWhite());
+        assertEquals(5, mana.getBlack());
+        assertEquals(6, mana.getColorless());
+        assertEquals(7, mana.getAny());
+    }
+
+
+    @Test
+    public void shouldNotAllowNegativeIntegers() {
+        // given
+
+        // when
+        Mana mana = new Mana(-1, 2, 3, 4, 5, 6, 7);
+
+        // then
+        assertEquals(0, mana.getRed());
+    }
+
+
+    @Test
+    public void shouldCreateRedMana() {
+
+        // when
+        Mana mana = Mana.RedMana(1);
+
+        // then
+        assertEquals(1, mana.getRed());
+    }
+
+
+    @Test
+    public void shouldCreateGreenMana() {
+
+        // when
+        Mana mana = Mana.GreenMana(1);
+
+        // then
+        assertEquals(1, mana.getGreen());
+    }
+
+
+    @Test
+    public void shouldCreateBlueMana() {
+
+        // when
+        Mana mana = Mana.BlueMana(1);
+
+        // then
+        assertEquals(1, mana.getBlue());
+    }
+
+
+    @Test
+    public void shouldCreateWhiteMana() {
+
+        // when
+        Mana mana = Mana.WhiteMana(1);
+
+        // then
+        assertEquals(1, mana.getWhite());
+    }
+
+
+    @Test
+    public void shouldCreateBlackMana() {
+
+        // when
+        Mana mana = Mana.BlackMana(1);
+
+        // then
+        assertEquals(1, mana.getBlack());
+    }
+
+
+    @Test
+    public void shouldCreateColorlessMana() {
+
+        // when
+        Mana mana = Mana.ColorlessMana(1);
+
+        // then
+        assertEquals(1, mana.getColorless());
+    }
+
+
+    @Test
+    public void shouldNotAllowNegativeRedMana() {
+        // given
+
+        // when
+        Mana mana = Mana.RedMana(-1);
+
+        //then
+        assertEquals(0, mana.getRed());
+    }
+
+
+    @Test
+    public void shouldNotAllowNegativeGreenMana() {
+        // given
+
+        // when
+        Mana mana = Mana.GreenMana(-1);
+
+        //then
+        assertEquals(0, mana.getGreen());
+    }
+
+
+    @Test
+    public void shouldNotAllowNegativeBlueMana() {
+        // given
+
+        // when
+        Mana mana = Mana.BlueMana(-1);
+
+        //then
+        assertEquals(0, mana.getBlue());
+    }
+
+
+    @Test
+    public void shouldNotAllowNegativeWhiteMana() {
+        // given
+
+        // when
+        Mana mana = Mana.WhiteMana(-1);
+
+        //then
+        assertEquals(0, mana.getWhite());
+    }
+
+
+    @Test
+    public void shouldNotAllowNegativeBlackMana() {
+        // given
+
+        // when
+        Mana mana = Mana.BlackMana(-1);
+
+        //then
+        assertEquals(0, mana.getBlack());
+    }
+
+
+    @Test
+    public void shouldNotAllowNegativeColorlessMana() {
+        // given
+
+        // when
+        Mana mana = Mana.ColorlessMana(-1);
+
+        //then
+        assertEquals(0, mana.getColorless());
+    }
+
+
+    @Test
+    public void shouldAddMana() {
+        // given
+        Mana thisMana = new Mana(1, 2, 3, 4, 5, 6, 7);
+        Mana thatMana = new Mana(1, 2, 3, 4, 5, 6, 7);
+
+
+        // when
+        thisMana.add(thatMana);
+
+        // then
+        assertEquals(2, thisMana.getRed());
+        assertEquals(4, thisMana.getGreen());
+        assertEquals(6, thisMana.getBlue());
+        assertEquals(8, thisMana.getWhite());
+        assertEquals(10, thisMana.getBlack());
+        assertEquals(12, thisMana.getColorless());
+        assertEquals(14, thisMana.getAny());
+    }
+
+
+    @Test
+    public void shouldIncreaseRedMana() {
+        // given
+        Mana mana = new Mana();
+
+        // when
+        mana.increaseRed();
+
+        // then
+        assertEquals(1, mana.getRed());
+    }
+
+
+    @Test
+    public void shouldIncreaseGreenMana() {
+        // given
+        Mana mana = new Mana();
+
+        // when
+        mana.increaseGreen();
+
+        // then
+        assertEquals(1, mana.getGreen());
+    }
+
+    @Test
+    public void shouldIncreaseBlueMana() {
+        // given
+        Mana mana = new Mana();
+
+        // when
+        mana.increaseBlue();
+
+        // then
+        assertEquals(1, mana.getBlue());
+    }
+
+    @Test
+    public void shouldIncreaseWhiteMana() {
+        // given
+        Mana mana = new Mana();
+
+        // when
+        mana.increaseWhite();
+
+        // then
+        assertEquals(1, mana.getWhite());
+    }
+
+    @Test
+    public void shouldIncreaseBlackMana() {
+        // given
+        Mana mana = new Mana();
+
+        // when
+        mana.increaseBlack();
+
+        // then
+        assertEquals(1, mana.getBlack());
+    }
+
+    @Test
+    public void shouldIncreaseColorlessMana() {
+        // given
+        Mana mana = new Mana();
+
+        // when
+        mana.increaseColorless();
+
+        // then
+        assertEquals(1, mana.getColorless());
+    }
+
+    @Test
+    public void shouldSubtractMana() {
+        // given
+        Mana thisMana = new Mana(2, 2, 2, 2, 2, 2, 2);
+        Mana thatMana = new Mana(1, 1, 1, 1, 1, 1, 1);
+
+        // when
+        thisMana.subtract(thatMana);
+
+        // then
+        assertEquals(1, thisMana.getRed());
+        assertEquals(1, thisMana.getGreen());
+        assertEquals(1, thisMana.getBlue());
+        assertEquals(1, thisMana.getWhite());
+        assertEquals(1, thisMana.getBlack());
+        assertEquals(1, thisMana.getColorless());
+        assertEquals(1, thisMana.getAny());
+    }
+
+    @Test
+    public void shouldNotSubtractLessThan0() {
+        // given
+        Mana thisMana = new Mana(2, 2, 2, 2, 2, 2, 2);
+        Mana thatMana = new Mana(10, 1, 1, 1, 10, 1, 1);
+
+        // when
+        thisMana.subtract(thatMana);
+
+        // then
+        assertEquals(-8, thisMana.getRed());
+        assertEquals(1, thisMana.getGreen());
+        assertEquals(1, thisMana.getBlue());
+        assertEquals(1, thisMana.getWhite());
+        assertEquals(-8, thisMana.getBlack());
+        assertEquals(1, thisMana.getColorless());
+        assertEquals(1, thisMana.getAny());
+    }
+
+
+    @Test
+    public void shouldReturnCount() {
+        // given
+        Mana mana = new Mana(1, 2, 3, 4, 5, 6, 7);
+        FilterMana filter = new FilterMana();
+        filter.setBlack(true);
+
+        // when
+        int totalCount = mana.count();
+        int coloredCount = mana.countColored();
+        int filteredMana = mana.count(filter);
+
+        // then
+        assertEquals(28, totalCount);
+        assertEquals(22, coloredCount);
+        assertEquals(5, filteredMana);
+    }
+
+
+    @Test
+    public void shouldReturnString() {
+        // given
+        Mana mana = new Mana(1, 2, 3, 0, 3, 6, 2);
+
+        // when
+        String ret = mana.toString();
+
+        // then
+        assertEquals("{6}{R}{G}{G}{U}{U}{U}{B}{B}{B}{Any}{Any}", ret);
+    }
+
+    @Test
+    public void shouldClearMana() {
+        // given
+        Mana mana = new Mana(1, 2, 3, 4, 5, 6, 7);
+
+        // when
+        mana.clear();
+
+        // then
+        assertEquals(0, mana.getRed());
+        assertEquals(0, mana.getGreen());
+        assertEquals(0, mana.getBlue());
+        assertEquals(0, mana.getWhite());
+        assertEquals(0, mana.getBlack());
+        assertEquals(0, mana.getColorless());
+        assertEquals(0, mana.getAny());
+    }
+
+
+    @Test
+    public void shouldReturnCopy() {
+        // given
+        Mana mana = new Mana(1, 2, 3, 4, 5, 6, 7);
+
+        // when
+        Mana copy = mana.copy();
+
+        // then
+        assertEquals(mana, copy); // are equal
+        assertFalse(mana == copy); // are not the same object
+    }
+
+    @Test
+    public void shouldGetColorByColoredManaSymbol() {
+        // given
+        Mana mana = new Mana(1, 1, 1, 1, 1, 1, 1);
+
+        // when
+        int redMana = mana.getColor(ColoredManaSymbol.R);
+        int greenMana = mana.getColor(ColoredManaSymbol.G);
+        int blueMana = mana.getColor(ColoredManaSymbol.U);
+        int blackMana = mana.getColor(ColoredManaSymbol.B);
+        int whiteMana = mana.getColor(ColoredManaSymbol.W);
+
+        // then
+        assertEquals(1, redMana);
+        assertEquals(1, greenMana);
+        assertEquals(1, blueMana);
+        assertEquals(1, blackMana);
+        assertEquals(1, whiteMana);
+    }
+
+
+    @Test
+    public void shouldGetColorByManaType() {
+        // given
+        Mana mana = new Mana(1, 1, 1, 1, 1, 1, 1);
+
+        // when
+        int redMana = mana.get(ManaType.RED);
+        int greenMana = mana.get(ManaType.GREEN);
+        int blueMana = mana.get(ManaType.BLUE);
+        int blackMana = mana.get(ManaType.BLACK);
+        int whiteMana = mana.get(ManaType.WHITE);
+        int colorlessMana = mana.get(ManaType.COLORLESS);
+
+        // then
+        assertEquals(1, redMana);
+        assertEquals(1, greenMana);
+        assertEquals(1, blueMana);
+        assertEquals(1, blackMana);
+        assertEquals(1, whiteMana);
+        assertEquals(1, colorlessMana);
+    }
+
+
+    @Test
+    public void shouldSetManaFromType() {
+        // given
+        Mana mana = new Mana();
+
+        // when
+        mana.set(ManaType.BLACK, 3);
+        mana.set(ManaType.BLUE, 4);
+        mana.set(ManaType.RED, 5);
+        mana.set(ManaType.GREEN, 6);
+        mana.set(ManaType.WHITE, 7);
+        mana.set(ManaType.COLORLESS, 8);
+
+        // then
+        assertEquals(3, mana.getBlack());
+        assertEquals(4, mana.getBlue());
+        assertEquals(5, mana.getRed());
+        assertEquals(6, mana.getGreen());
+        assertEquals(7, mana.getWhite());
+        assertEquals(8, mana.getColorless());
+    }
+
+    @Test
+    public void shouldSetToMana() {
+        // given
+        Mana mana = new Mana();
+        Mana newMana = new Mana(1, 2, 3, 4, 5, 6, 7);
+
+        // when
+        mana.setToMana(newMana);
+
+        // then
+        assertEquals(mana, newMana);
+        assertFalse(mana == newMana);
+    }
+
+
+    @Test
+    public void shouldHaveEqualManaValue() {
+        // given
+        Mana mana = new Mana(1, 2, 3, 4, 5, 6, 7);
+        Mana newMana = new Mana(1, 2, 3, 4, 5, 6, 7);
+
+        // when
+        boolean equalMana = mana.equalManaValue(newMana);
+
+        // then
+        assertTrue(equalMana);
+    }
+
+
+    @Test
+    public void shouldGetDifferentColors() {
+        // given
+        Mana mana = new Mana();
+        mana.setRed(3);
+        mana.setGreen(2);
+
+        // when
+        int colors = mana.getDifferentColors();
+
+        // then
+        assertEquals(2, colors);
+    }
+
+
+    @Test
+    public void shouldNotSetManaLessThanZero() {
+        // given
+        Mana mana = new Mana();
+
+        // when
+        mana.setRed(-4);
+        mana.setGreen(-4);
+        mana.setBlue(-4);
+        mana.setWhite(-4);
+        mana.setBlack(-4);
+        mana.setColorless(-4);
+        mana.setAny(-4);
+
+        // then
+        assertEquals(0, mana.getRed());
+        assertEquals(0, mana.getGreen());
+        assertEquals(0, mana.getBlue());
+        assertEquals(0, mana.getWhite());
+        assertEquals(0, mana.getBlack());
+        assertEquals(0, mana.getColorless());
+        assertEquals(0, mana.getAny());
+    }
+}
diff --git a/Mage/src/mage/Mana.java b/Mage/src/mage/Mana.java
index e5dace32df..0038727309 100644
--- a/Mage/src/mage/Mana.java
+++ b/Mage/src/mage/Mana.java
@@ -28,19 +28,32 @@
 package mage;
 
 import java.io.Serializable;
+import java.util.Objects;
+import java.util.logging.Logger;
+
 import mage.constants.ColoredManaSymbol;
 import mage.constants.ManaType;
-import static mage.constants.ManaType.COLORLESS;
 import mage.filter.FilterMana;
 import mage.util.Copyable;
-import mage.util.ThreadLocalStringBuilder;
+import mage.util.Logging;
 
 /**
+ * Representation of a mana pool. Can contain colored and colorless mana.
  *
  * @author BetaSteward_at_googlemail.com
  */
 public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
 
+    private static Logger logger = Logging.getLogger(Mana.class.getName());
+
+    public static final String RED = "RED";
+    public static final String GREEN = "GREEN";
+    public static final String BLUE = "BLUE";
+    public static final String WHITE = "WHITE";
+    public static final String BLACK = "BLACK";
+    public static final String COLORLESS = "COLORLESS";
+    public static final String ANY = "ANY";
+
     protected int red;
     protected int green;
     protected int blue;
@@ -50,6 +63,7 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
     protected int any;
     protected boolean flag = false;
 
+    //todo unsafe and mutable
     public static final Mana RedMana = RedMana(1);
     public static final Mana GreenMana = GreenMana(1);
     public static final Mana BlueMana = BlueMana(1);
@@ -60,7 +74,13 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
     public Mana() {
     }
 
+    /**
+     * Copy constructor.
+     *
+     * @param mana The {@link Mana} to copy from. Can not be null.
+     */
     public Mana(final Mana mana) {
+        Objects.requireNonNull(mana, "The passed in Mana can not be null");
         this.red = mana.red;
         this.green = mana.green;
         this.blue = mana.blue;
@@ -71,7 +91,38 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
         this.flag = mana.flag;
     }
 
-    public Mana(ColoredManaSymbol color) {
+
+    /**
+     * Creates a {@link Mana} object with the mana passed in.
+     *
+     * @param red       Total red mana to add.
+     * @param green     Total green mana to add.
+     * @param blue      Total blue mana to add.
+     * @param white     Total white mana to add.
+     * @param black     Total black mana to add.
+     * @param colorless Total colorless mana to add.
+     * @param any       Total any colored mana to add.
+     */
+    public Mana(final int red, final int green, final int blue, final int white,
+                final int black, final int colorless, final int any) {
+        this.red = notNegative(red, RED);
+        this.green = notNegative(green, GREEN);
+        this.blue = notNegative(blue, BLUE);
+        this.white = notNegative(white, WHITE);
+        this.black = notNegative(black, BLACK);
+        this.colorless = notNegative(colorless, COLORLESS);
+        this.any = notNegative(any, ANY);
+    }
+
+
+    /**
+     * Creates a {@link Mana} object from the {@link ColoredManaSymbol} {@code color}.
+     *
+     * @param color The {@link ColoredManaSymbol} to create {@link Mana} from.
+     *              Can not be null.
+     */
+    public Mana(final ColoredManaSymbol color) {
+        Objects.requireNonNull(color, "The passed in ColoredManaSymbol can not be null");
         switch (color) {
             case G:
                 green = 1;
@@ -88,95 +139,154 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
             case W:
                 white = 1;
                 break;
+            default:
+                throw new IllegalArgumentException("Unknown color " + color.getColorName());
         }
     }
 
-    public static Mana RedMana(int num) {
-        return new Mana(num, 0, 0, 0, 0, 0, 0);
+    /**
+     * Creates a {@link Mana} object with {@code num} Red mana.
+     *
+     * @param num The amount of Red mana to add. Can not be negative.
+     * @return {@link Mana} object with {@code num} Red mana.
+     */
+    public static Mana RedMana(final int num) {
+        return new Mana(notNegative(num, RED), 0, 0, 0, 0, 0, 0);
     }
 
-    public static Mana GreenMana(int num) {
-        return new Mana(0, num, 0, 0, 0, 0, 0);
+    /**
+     * Creates a {@link Mana} object with {@code num} Green mana.
+     *
+     * @param num The amount of Green mana to add. Can not be negative.
+     * @return {@link Mana} object with {@code num} Green mana.
+     */
+    public static Mana GreenMana(final int num) {
+        return new Mana(0, notNegative(num, GREEN), 0, 0, 0, 0, 0);
     }
 
-    public static Mana BlueMana(int num) {
-        return new Mana(0, 0, num, 0, 0, 0, 0);
+    /**
+     * Creates a {@link Mana} object with {@code num} Blue mana.
+     *
+     * @param num The amount of Blue mana to add. Can not be negative.
+     * @return {@link Mana} object with {@code num} Blue mana.
+     */
+    public static Mana BlueMana(final int num) {
+        return new Mana(0, 0, notNegative(num, BLUE), 0, 0, 0, 0);
     }
 
-    public static Mana WhiteMana(int num) {
-        return new Mana(0, 0, 0, num, 0, 0, 0);
+    /**
+     * Creates a {@link Mana} object with {@code num} White mana.
+     *
+     * @param num The amount of White mana to add. Can not be negative.
+     * @return {@link Mana} object with {@code num} White mana.
+     */
+    public static Mana WhiteMana(final int num) {
+        return new Mana(0, 0, 0, notNegative(num, WHITE), 0, 0, 0);
     }
 
-    public static Mana BlackMana(int num) {
-        return new Mana(0, 0, 0, 0, num, 0, 0);
+    /**
+     * Creates a {@link Mana} object with {@code num} Black mana.
+     *
+     * @param num The amount of Black mana to add. Can not be negative.
+     * @return {@link Mana} object with {@code num} Black mana.
+     */
+    public static Mana BlackMana(final int num) {
+        return new Mana(0, 0, 0, 0, notNegative(num, BLACK), 0, 0);
     }
 
-    public static Mana ColorlessMana(int num) {
-        return new Mana(0, 0, 0, 0, 0, num, 0);
+    /**
+     * Creates a {@link Mana} object with {@code num} Colorless mana.
+     *
+     * @param num The amount of Colorless mana to add. Can not be negative.
+     * @return {@link Mana} object with {@code num} Colorless mana.
+     */
+    public static Mana ColorlessMana(final int num) {
+        return new Mana(0, 0, 0, 0, 0, notNegative(num, COLORLESS), 0);
     }
 
-    public Mana(int red, int green, int blue, int white, int black, int colorless, int any) {
-        this.red = red;
-        this.green = green;
-        this.blue = blue;
-        this.white = white;
-        this.black = black;
-        this.colorless = colorless;
-        this.any = any;
+
+    /**
+     * Increases the mana in this object by the relative mana in the passed in {@link Mana} object.
+     *
+     * @param mana {@link Mana} object to increase this mana by.
+     */
+    public void add(final Mana mana) {
+        red += mana.red;
+        green += mana.green;
+        blue += mana.blue;
+        white += mana.white;
+        black += mana.black;
+        colorless += mana.colorless;
+        any += mana.any;
     }
 
-    public void add(Mana mana) {
-        red += mana.getRed();
-        green += mana.getGreen();
-        blue += mana.getBlue();
-        white += mana.getWhite();
-        black += mana.getBlack();
-        colorless += mana.getColorless();
-        any += mana.getAny();
-    }
-
-    public void addRed() {
+    /**
+     * Increases the Red mana by one.
+     */
+    public void increaseRed() {
         red++;
     }
 
-    public void addGreen() {
+    /**
+     * Increases the Green mana by one.
+     */
+    public void increaseGreen() {
         green++;
     }
 
-    public void addBlue() {
+    /**
+     * Increases the Blue mana by one.
+     */
+    public void increaseBlue() {
         blue++;
     }
 
-    public void addWhite() {
+    /**
+     * Increases the White mana by one.
+     */
+    public void increaseWhite() {
         white++;
     }
 
-    public void addBlack() {
+    /**
+     * Increases the Black mana by one.
+     */
+    public void increaseBlack() {
         black++;
     }
 
-    public void addColorless() {
+    /**
+     * Increases the Colorless mana by one.
+     */
+    public void increaseColorless() {
         colorless++;
     }
 
-    public void subtract(Mana mana) {
-        red -= mana.getRed();
-        green -= mana.getGreen();
-        blue -= mana.getBlue();
-        white -= mana.getWhite();
-        black -= mana.getBlack();
-        colorless -= mana.getColorless();
-        any -= mana.getAny();
+    /**
+     * Subtracts the passed in mana values from this instance. Will not
+     * reduce this instances mana below 0.
+     *
+     * @param mana mana values to subtract
+     */
+    public void subtract(final Mana mana) {
+        red -= mana.red;
+        green -= mana.green;
+        blue -= mana.blue;
+        white -= mana.white;
+        black -= mana.black;
+        colorless -= mana.colorless;
+        any -= mana.any;
     }
 
     public void subtractCost(Mana cost) {
-        red -= cost.getRed();
-        green -= cost.getGreen();
-        blue -= cost.getBlue();
-        white -= cost.getWhite();
-        black -= cost.getBlack();
-        any -= cost.getAny();
-        colorless -= cost.getColorless();
+        red -= cost.red;
+        green -= cost.green;
+        blue -= cost.blue;
+        white -= cost.white;
+        black -= cost.black;
+        any -= cost.any;
+        colorless -= cost.colorless;
+
         while (colorless < 0) {
             int oldColorless = colorless;
             if (red > 0) {
@@ -213,15 +323,72 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
         }
     }
 
+    /**
+     * Sets this object's mana to be equal to the passed in {@code mana}
+     *
+     * @param mana the mana to copy from
+     */
+    public void setToMana(final Mana mana) {
+        any = mana.any;
+        red = mana.red;
+        green = mana.green;
+        white = mana.white;
+        blue = mana.blue;
+        black = mana.black;
+        colorless = mana.colorless;
+    }
+
+    /**
+     * Returns the total mana count.
+     *
+     * @return the total mana count.
+     */
     public int count() {
         return red + green + blue + white + black + colorless + any;
     }
 
+    /**
+     * Returns the total colored mana count.
+     *
+     * @return the total colored mana count.
+     */
     public int countColored() {
         return red + green + blue + white + black + any;
     }
 
-    public int count(FilterMana filter) {
+
+    /**
+     * Returns how many colors are currently more than 0.
+     *
+     * @return how many colors are currently more than 0.
+     */
+    public int getDifferentColors() {
+        int count = 0;
+        if (blue > 0) {
+            count++;
+        }
+        if (black > 0) {
+            count++;
+        }
+        if (green > 0) {
+            count++;
+        }
+        if (white > 0) {
+            count++;
+        }
+        if (red > 0) {
+            count++;
+        }
+        return count;
+    }
+
+    /**
+     * Returns the total mana with a {@link FilterMana} applied.
+     *
+     * @param filter the filter to apply when counting mana
+     * @return the total mana after filtration.
+     */
+    public int count(final FilterMana filter) {
         if (filter == null) {
             return count();
         }
@@ -247,6 +414,9 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
         return count;
     }
 
+    /**
+     * Resets all mana to 0
+     */
     public void clear() {
         red = 0;
         green = 0;
@@ -257,6 +427,11 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
         any = 0;
     }
 
+    /**
+     * Returns {@link String} of internal state.
+     *
+     * @return text version of internal state.
+     */
     @Override
     public String toString() {
         StringBuilder sbMana = new StringBuilder();
@@ -284,14 +459,24 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
         return sbMana.toString();
     }
 
-    private static final transient ThreadLocalStringBuilder threadLocalBuilder = new ThreadLocalStringBuilder(10);
 
+    /**
+     * Returns a deep copy of this object
+     *
+     * @return a deep copy of this object
+     */
     @Override
     public Mana copy() {
         return new Mana(this);
     }
 
-    public boolean enough(Mana avail) {
+    /**
+     * Returns if there is enough mana available compared to the passed in {@link Mana}
+     *
+     * @param avail value to compare with
+     * @return if there is enough mana in the mana pool compared to the passed in {@link Mana}
+     */
+    public boolean enough(final Mana avail) {
         Mana compare = avail.copy();
         compare.subtract(this);
         if (compare.getRed() < 0) {
@@ -338,7 +523,13 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
         return true;
     }
 
-    public Mana needed(Mana avail) {
+    /**
+     * Returns how much mana is needed to meet the passed in cost
+     *
+     * @param avail mana cost to meet
+     * @return how much mana is needed to meet the passed in cost
+     */
+    public Mana needed(final Mana avail) {
         Mana compare = avail.copy();
         compare.subtract(this);
         if (compare.getRed() < 0 && compare.getAny() > 0) {
@@ -405,8 +596,8 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
         return red;
     }
 
-    public void setRed(int red) {
-        this.red = red;
+    public void setRed(final int red) {
+        this.red = notNegative(red, "Red");
     }
 
     public int getGreen() {
@@ -414,7 +605,7 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
     }
 
     public void setGreen(int green) {
-        this.green = green;
+        this.green = notNegative(green, "Green");
     }
 
     public int getBlue() {
@@ -422,7 +613,7 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
     }
 
     public void setBlue(int blue) {
-        this.blue = blue;
+        this.blue = notNegative(blue, "Blue");
     }
 
     public int getWhite() {
@@ -430,7 +621,7 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
     }
 
     public void setWhite(int white) {
-        this.white = white;
+        this.white = notNegative(white, "White");
     }
 
     public int getBlack() {
@@ -438,7 +629,7 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
     }
 
     public void setBlack(int black) {
-        this.black = black;
+        this.black = notNegative(black, "Black");
     }
 
     public int getColorless() {
@@ -446,7 +637,7 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
     }
 
     public void setColorless(int colorless) {
-        this.colorless = colorless;
+        this.colorless = notNegative(colorless, "Colorless");
     }
 
     public int getAny() {
@@ -454,43 +645,51 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
     }
 
     public void setAny(int any) {
-        this.any = any;
+        this.any = notNegative(any, "Any");
     }
 
+
     @Override
-    public int compareTo(Mana o) {
-        return this.count() - o.count();
+    public int compareTo(final Mana o) {
+        return count() - o.count();
     }
 
     /**
-     *
      * @param mana
      * @return true if this contains any values that mana has
      */
+    // todo what purpose does this serve?
+    // todo what if you want to check for red, and you have black?
     public boolean contains(Mana mana) {
-        if (mana.black > 0 && this.black > 0) {
+        if (mana.black > 0 && black > 0) {
             return true;
         }
-        if (mana.blue > 0 && this.blue > 0) {
+        if (mana.blue > 0 && blue > 0) {
             return true;
         }
-        if (mana.red > 0 && this.red > 0) {
+        if (mana.red > 0 && red > 0) {
             return true;
         }
-        if (mana.white > 0 && this.white > 0) {
+        if (mana.white > 0 && white > 0) {
             return true;
         }
-        if (mana.green > 0 && this.green > 0) {
+        if (mana.green > 0 && green > 0) {
             return true;
         }
-        if (mana.colorless > 0 && this.count() > 0) {
+        if (mana.colorless > 0 && count() > 0) {
             return true;
         }
 
         return false;
     }
 
-    public int getColor(ColoredManaSymbol color) {
+    /**
+     * Returns the total color based on the {@link ColoredManaSymbol} passed in
+     *
+     * @param color the {@link ColoredManaSymbol} to get mana for
+     * @return the total color based on the {@link ColoredManaSymbol} passed in
+     */
+    public int getColor(final ColoredManaSymbol color) {
         if (color.equals(ColoredManaSymbol.G)) {
             return getGreen();
         }
@@ -509,7 +708,13 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
         return 0;
     }
 
-    public int get(ManaType manaType) {
+    /**
+     * Returns the total color based on the {@link ManaType} passed in
+     *
+     * @param manaType the {@link ManaType} to return the color for
+     * @return the total color based on the {@link ManaType} passed in
+     */
+    public int get(final ManaType manaType) {
         switch (manaType) {
             case BLACK:
                 return black;
@@ -527,7 +732,14 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
         return 0;
     }
 
-    public void set(ManaType manaType, int amount) {
+    /**
+     * Sets the total mana based on the passed int {@code manaType} and {@code amount}
+     *
+     * @param manaType the type of mana
+     * @param amount   the amount to set the mana to, can not be negative
+     */
+    public void set(final ManaType manaType, final int amount) {
+        notNegative(amount, manaType.toString());
         switch (manaType) {
             case BLACK:
                 black = amount;
@@ -550,6 +762,7 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
         }
     }
 
+    //todo not sure what this does, should we add some documentation of what a flag is?
     public void setFlag(boolean flag) {
         this.flag = flag;
     }
@@ -558,24 +771,21 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
         return flag;
     }
 
-    public void setToMana(Mana mana) {
-        this.any = mana.any;
-        this.red = mana.red;
-        this.green = mana.green;
-        this.white = mana.white;
-        this.blue = mana.blue;
-        this.black = mana.black;
-        this.colorless = mana.colorless;
-    }
 
-    public boolean equalManaValue(Mana mana) {
-        return this.any == mana.any
-                && this.red == mana.red
-                && this.green == mana.green
-                && this.white == mana.white
-                && this.blue == mana.blue
-                && this.black == mana.black
-                && this.colorless == mana.colorless;
+    /**
+     * Checks if this object has the same mana values as the passed in {@link Mana}
+     *
+     * @param mana the {@link Mana} to compare to
+     * @return if both {@link Mana} objects have the same mana values
+     */
+    public boolean equalManaValue(final Mana mana) {
+        return any == mana.any
+                && red == mana.red
+                && green == mana.green
+                && white == mana.white
+                && blue == mana.blue
+                && black == mana.black
+                && colorless == mana.colorless;
     }
 
     /**
@@ -586,14 +796,13 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
      * @return
      */
     public boolean includesMana(Mana mana) {
-        return this.green >= mana.green
-                && this.blue >= mana.blue
-                && this.white >= mana.white
-                && this.black >= mana.black
-                && this.red >= mana.red
-                && (this.colorless >= mana.colorless
-                || this.countColored() >= mana.countColored() + mana.colorless);
-
+        return green >= mana.green
+                && blue >= mana.blue
+                && white >= mana.white
+                && black >= mana.black
+                && red >= mana.red
+                && (colorless >= mana.colorless
+                || countColored() >= mana.countColored() + mana.colorless);
     }
 
     /**
@@ -628,23 +837,49 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
         return moreMana;
     }
 
-    public int getDifferentColors() {
-        int count = 0;
-        if (blue > 0) {
-            count++;
+
+    /**
+     * Used to check if a passed in value is less than 0. Log if the value is.
+     *
+     * @param value     The value to check
+     * @param valueName The name of the value
+     * @return 0 if less than 0, or the value if more than 0
+     */
+    private static int notNegative(int value, final String valueName) {
+        if (value < 0) {
+            logger.info(valueName + " can not be set to less than 0. Setting to 0");
+            value = 0;
         }
-        if (black > 0) {
-            count++;
-        }
-        if (green > 0) {
-            count++;
-        }
-        if (white > 0) {
-            count++;
-        }
-        if (red > 0) {
-            count++;
-        }
-        return count;
+        return value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Mana mana = (Mana) o;
+
+        if (red != mana.red) return false;
+        if (green != mana.green) return false;
+        if (blue != mana.blue) return false;
+        if (white != mana.white) return false;
+        if (black != mana.black) return false;
+        if (colorless != mana.colorless) return false;
+        if (any != mana.any) return false;
+        return flag == mana.flag;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = red;
+        result = 31 * result + green;
+        result = 31 * result + blue;
+        result = 31 * result + white;
+        result = 31 * result + black;
+        result = 31 * result + colorless;
+        result = 31 * result + any;
+        result = 31 * result + (flag ? 1 : 0);
+        return result;
     }
 }
diff --git a/Mage/src/mage/abilities/costs/mana/ManaCostImpl.java b/Mage/src/mage/abilities/costs/mana/ManaCostImpl.java
index c33e0f5799..11c4a66e9a 100644
--- a/Mage/src/mage/abilities/costs/mana/ManaCostImpl.java
+++ b/Mage/src/mage/abilities/costs/mana/ManaCostImpl.java
@@ -118,31 +118,31 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost {
         switch (mana) {
             case B:
                 if (pool.pay(ManaType.BLACK, ability, sourceFilter, game)) {
-                    this.payment.addBlack();
+                    this.payment.increaseBlack();
                     return true;
                 }
                 break;
             case U:
                 if (pool.pay(ManaType.BLUE, ability, sourceFilter, game)) {
-                    this.payment.addBlue();
+                    this.payment.increaseBlue();
                     return true;
                 }
                 break;
             case W:
                 if (pool.pay(ManaType.WHITE, ability, sourceFilter, game)) {
-                    this.payment.addWhite();
+                    this.payment.increaseWhite();
                     return true;
                 }
                 break;
             case G:
                 if (pool.pay(ManaType.GREEN, ability, sourceFilter, game)) {
-                    this.payment.addGreen();
+                    this.payment.increaseGreen();
                     return true;
                 }
                 break;
             case R:
                 if (pool.pay(ManaType.RED, ability, sourceFilter, game)) {
-                    this.payment.addRed();
+                    this.payment.increaseRed();
                     return true;
                 }
                 break;
@@ -154,27 +154,27 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost {
         int conditionalCount = pool.getConditionalCount(ability, game, null);
         while (mana > payment.count() && (pool.count() > 0 || conditionalCount > 0)) {
             if (pool.pay(ManaType.COLORLESS, ability, sourceFilter, game)) {
-                this.payment.addColorless();
+                this.payment.increaseColorless();
                 continue;
             }
             if (pool.pay(ManaType.BLACK, ability, sourceFilter, game)) {
-                this.payment.addBlack();
+                this.payment.increaseBlack();
                 continue;
             }
             if (pool.pay(ManaType.BLUE, ability, sourceFilter, game)) {
-                this.payment.addBlue();
+                this.payment.increaseBlue();
                 continue;
             }
             if (pool.pay(ManaType.WHITE, ability, sourceFilter, game)) {
-                this.payment.addWhite();
+                this.payment.increaseWhite();
                 continue;
             }
             if (pool.pay(ManaType.GREEN, ability, sourceFilter, game)) {
-                this.payment.addGreen();
+                this.payment.increaseGreen();
                 continue;
             }
             if (pool.pay(ManaType.RED, ability, sourceFilter, game)) {
-                this.payment.addRed();
+                this.payment.increaseRed();
                 continue;
             }
             break;
diff --git a/Mage/src/mage/abilities/effects/common/DynamicManaEffect.java b/Mage/src/mage/abilities/effects/common/DynamicManaEffect.java
index d6f5cf0108..6d6cc7597a 100644
--- a/Mage/src/mage/abilities/effects/common/DynamicManaEffect.java
+++ b/Mage/src/mage/abilities/effects/common/DynamicManaEffect.java
@@ -154,15 +154,15 @@ public class DynamicManaEffect extends BasicManaEffect {
                             }
                         }
                         if (choiceColor.getColor().isBlack()) {
-                            computedMana.addBlack();
+                            computedMana.increaseBlack();
                         } else if (choiceColor.getColor().isBlue()) {
-                            computedMana.addBlue();
+                            computedMana.increaseBlue();
                         } else if (choiceColor.getColor().isRed()) {
-                            computedMana.addRed();
+                            computedMana.increaseRed();
                         } else if (choiceColor.getColor().isGreen()) {
-                            computedMana.addGreen();
+                            computedMana.increaseGreen();
                         } else if (choiceColor.getColor().isWhite()) {
-                            computedMana.addWhite();
+                            computedMana.increaseWhite();
                         }
                         if (!oneChoice) {
                             choiceColor.clearChoice();
diff --git a/Mage/src/mage/abilities/effects/common/continuous/CommanderManaReplacementEffect.java b/Mage/src/mage/abilities/effects/common/continuous/CommanderManaReplacementEffect.java
index 36ad215d04..b3e4e3de2c 100644
--- a/Mage/src/mage/abilities/effects/common/continuous/CommanderManaReplacementEffect.java
+++ b/Mage/src/mage/abilities/effects/common/continuous/CommanderManaReplacementEffect.java
@@ -81,31 +81,31 @@ public class CommanderManaReplacementEffect extends ReplacementEffectImpl {
         Mana mana = ((ManaEvent) event).getMana();
         if (mana.getBlack() > 0 && !commanderMana.isBlack()) {
             for (int i = 0; i < mana.getBlack(); i++) {
-                mana.addColorless();
+                mana.increaseColorless();
             }
             mana.setBlack(0);
         }
         if (mana.getBlue() > 0 && !commanderMana.isBlue()) {
             for (int i = 0; i < mana.getBlue(); i++) {
-                mana.addColorless();
+                mana.increaseColorless();
             }
             mana.setBlue(0);
         }
         if (mana.getGreen() > 0 && !commanderMana.isGreen()) {
             for (int i = 0; i < mana.getGreen(); i++) {
-                mana.addColorless();
+                mana.increaseColorless();
             }
             mana.setGreen(0);
         }
         if (mana.getRed() > 0 && !commanderMana.isRed()) {
             for (int i = 0; i < mana.getRed(); i++) {
-                mana.addColorless();
+                mana.increaseColorless();
             }
             mana.setRed(0);
         }
         if (mana.getWhite() > 0 && !commanderMana.isWhite()) {
             for (int i = 0; i < mana.getWhite(); i++) {
-                mana.addColorless();
+                mana.increaseColorless();
             }
             mana.setWhite(0);
         }