﻿namespace Infestation.Tests.Engine.HoldingPenTests
{
    using System;
    using System.Linq;
    using AbstractSubClasses;
    using NUnit.Framework;
    using Moq;

    [TestFixture]
    public class HoldingPen_Should
    {
        [TestCase("insert Dog Sharo")]
        [TestCase("insert Human Sharo")]
        [TestCase("insert Tank Sharo")]
        [TestCase("insert Marine Sharo")]
        [TestCase("insert Parasite Sharo")]
        public void InsertUnit_WhenExecuteInsertUnitCommandIsCalled(string insertCommands)
        {
            var holdingPen = new SubExtendedHoldingPen();

            var dog = new Dog("Sharo");

            holdingPen.ParseCommand(insertCommands);

            Assert.AreEqual(1, holdingPen.ContainedUnits.Count);
        }

        [Test]
        public void AttackAttackableUnits_WhenProceedCommandIsPassed()
        {
            var holdingPen = new SubExtendedHoldingPen();

            holdingPen.ParseCommand("insert Dog Sharo");
            holdingPen.ParseCommand("insert Tank Panzer");

            holdingPen.ParseCommand("proceed");

            Assert.AreEqual(1, holdingPen.ContainedUnits.Count);
        }

        [Test]
        public void AddAggressionCatalyst_SupplementCommandWordIsCalled()
        {
            var holdingPen = new SubExtendedHoldingPen();

            holdingPen.ParseCommand("insert Dog Sharo");

            holdingPen.ParseCommand("supplement AggressionCatalyst Sharo");

            var result = holdingPen.ContainedUnits.FirstOrDefault(x => x.Id == "Sharo");

            Assert.AreEqual(5, result.Aggression);
        }

        [Test]
        public void AddWeaponSupplement_SupplementCommandWordIsCalled()
        {
            var holdingPen = new SubExtendedHoldingPen();

            holdingPen.ParseCommand("insert Dog Sharo");

            holdingPen.ParseCommand("supplement Weapon Sharo");

            var result = holdingPen.ContainedUnits.FirstOrDefault(x => x.Id == "Sharo");

            Assert.AreEqual(2, result.Aggression);
        }

        [Test]
        public void AddWeaponHealthCatalystSupplement_SupplementCommandWordIsCalled()
        {
            var holdingPen = new SubExtendedHoldingPen();

            holdingPen.ParseCommand("insert Dog Sharo");

            holdingPen.ParseCommand("supplement HealthCatalyst Sharo");

            var result = holdingPen.ContainedUnits.FirstOrDefault(x => x.Id == "Sharo");

            Assert.AreEqual(7, result.Health);
        }

        [Test]
        public void AddPowerCatalystSupplement_SupplementCommandWordIsCalled()
        {
            var holdingPen = new SubExtendedHoldingPen();

            holdingPen.ParseCommand("insert Dog Sharo");

            holdingPen.ParseCommand("supplement PowerCatalyst Sharo");

            var result = holdingPen.ContainedUnits.FirstOrDefault(x => x.Id == "Sharo");

            Assert.AreEqual(8, result.Power);
        }

        [Test]
        public void ThrowIndexOutOfRangeException_WhenTryingToInsertObjectWithoutId()
        {
            var holdingPen = new SubExtendedHoldingPen();

            Assert.Throws<IndexOutOfRangeException>(() => holdingPen.ParseCommand("insert Dog"));
        }

        [Test]
        public void ThrowNotImplementedException_WhenTryingToAddInvalidSupplement()
        {
            var holdingPen = new SubExtendedHoldingPen();

            holdingPen.ParseCommand("insert Dog Sharo");

            Assert.Throws<NotImplementedException>(() => holdingPen.ParseCommand("supplement Power Sharo"));
        }

        [Test]
        public void ThrowIndexOutOfRangeException_WhenTryingToAddSupplementToNullUnit()
        {
            var holdingPen = new SubExtendedHoldingPen();

            holdingPen.ParseCommand("insert Dog Sharo");

            Assert.Throws<IndexOutOfRangeException>(() => holdingPen.ParseCommand("supplement PowerCatalyst"));
        }

        [Test]
        public void InfestAttackableUnits_WhenProceedCommandIsPassed()
        {
            var holdingPen = new SubExtendedHoldingPen();

            holdingPen.ParseCommand("insert Parasite Tereza");
            holdingPen.ParseCommand("insert Marine Tanya");

            holdingPen.ParseCommand("proceed");

            var result = holdingPen.ContainedUnits.FirstOrDefault(x => x.Id == "Tanya");

            Assert.AreEqual(3, result.Power);
        }
    }
}
