﻿namespace Cosmetics.Tests
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using NUnit.Framework;

    using Cosmetics.Common;
    using Cosmetics.Contracts;
    using Cosmetics.Engine;

    [TestFixture]
    public class CosmeticsFactoryTests
    {
        [TestCase("")]
        [TestCase(null)]
        public void CreateShampoo_ShouldThrow_WhenParameterIsNullOrEmpty(string input)
        {
            var factory = new CosmeticsFactory();

            Assert.Throws<NullReferenceException>(() => factory.CreateShampoo(input, "example", 5M, GenderType.Men, 500, UsageType.EveryDay));
        }

        [TestCase("ss")]
        [TestCase("asdfgasdfgasdfgasdfgasdgfdasdfa")]
        public void CreateShampoo_ShouldThrow_WhenInputIsOutOfRange(string input)
        {
            var factory = new CosmeticsFactory();

            Assert.Throws<IndexOutOfRangeException>(() => factory.CreateShampoo(input, "brand", 5M, GenderType.Unisex, 500, UsageType.EveryDay));
        }

        [TestCase("")]
        [TestCase(null)]
        public void CreateShampoo_ShouldThrow_WhenPassedBrandIsNullOrEmpty(string brand)
        {
            var factory = new CosmeticsFactory();

            Assert.Throws<NullReferenceException>(() => factory.CreateShampoo("thename", brand, 5M, GenderType.Women, 500, UsageType.Medical));
        }

        [TestCase("s")]
        [TestCase("asdasasdasdasfsdfgdsfgsdfgasdfasdfasd")]
        public void CreateShampoo_ShouldThrow_WhenPassedBrandIsOutOfRange(string brand)
        {
            var factory = new CosmeticsFactory();

            Assert.Throws<IndexOutOfRangeException>(() => factory.CreateShampoo("thename", brand, 5M, GenderType.Unisex, 500, UsageType.Medical));
        }

        [Test]
        public void CreateShampoo_ShouldReturnInstanceOfShampoo_WhenAllParamsAreValid()
        {
            var factory = new CosmeticsFactory();

            var expected = factory.CreateShampoo("shampoo", "thebrand", 5M, GenderType.Unisex, 500, UsageType.EveryDay);

            Assert.IsInstanceOf<IShampoo>(expected);
        }

        [TestCase("")]
        [TestCase(null)]
        public void CreateCategory_ShouldThrow_WhenPassedNameIsNullOrEmpty(string name)
        {
            var factory = new CosmeticsFactory();

            Assert.Throws<NullReferenceException>(() => factory.CreateCategory(name));
        }

        [TestCase("s")]
        [TestCase("asdasfsdgjnsdfjgsdfjgsdfhjghsdfjghsdfjghsdf")]
        public void CreateCategory_ShouldThrow_WhenPassedNameIsOutOfRange(string name)
        {
            var factory = new CosmeticsFactory();

            Assert.Throws<IndexOutOfRangeException>(() => factory.CreateCategory(name));
        }

        [Test]
        public void CreateCategory_ShouldReturnInstanceOfCategory_WhenNameIsValid()
        {
            var facotry = new CosmeticsFactory();

            var result = facotry.CreateCategory("category");

            Assert.IsInstanceOf<ICategory>(result);
        }

        [TestCase("")]
        [TestCase(null)]
        public void CreateToothPaste_ShouldThrow_WhenPassedNameIsNullOrEmpty(string name)
        {
            var factory = new CosmeticsFactory();

            Assert.Throws<NullReferenceException>(() => factory.CreateToothpaste(name, "thebrand", 5M, GenderType.Unisex, new List<string>() { "bilki", "nekwidrugiBilki" }));
        }

        [TestCase("ss")]
        [TestCase("asdasfsdjgsdflghdflkghdasdasdasdasf")]
        public void CreateToothPaste_ShouldThrow_WhenPassedNameIsOutOfRange(string name)
        {
            var factory = new CosmeticsFactory();

            Assert.Throws<IndexOutOfRangeException>(() => factory.CreateToothpaste(name, "THeBrand", 5M, GenderType.Unisex, new List<string>() { "sss", "ddd" }));
        }

        //Brand ToothPaste finito

        [TestCase("")]
        [TestCase(null)]
        public void CreateToothpaste_ShouldThrow_WhenPassedBrandIsNullOrEmpty(string brand)
        {
            var factory = new CosmeticsFactory();

            Assert.Throws<NullReferenceException>(() => factory.CreateToothpaste("theName", brand, 5M, GenderType.Unisex, new List<string>() { "sss", "ddd" }));
        }

        [TestCase("s")]
        [TestCase("asdasfdgfkdgkdfjgjsjdfgsadjfasdkjfasd")]
        public void Createtoothpaste_ShouldThrow_WhenPassedBrandIsWithInvalidLength(string brand)
        {
            var factory = new CosmeticsFactory();

            Assert.Throws<IndexOutOfRangeException>(() => factory.CreateToothpaste("theName", brand, 5M, GenderType.Unisex, new List<string>() { "sss", "ddd" }));
        }

        [Test]
        public void Createtoothpaste_ShouldReturnInstanceOfToothpaste_WhenAllParamsAreValid()
        {
            var factory = new CosmeticsFactory();

            var execResult = factory.CreateToothpaste("theName", "TheBrand", 5M, GenderType.Unisex, new List<string>() { "ssss", "dddd" });

            Assert.IsInstanceOf<IToothpaste>(execResult);
        }

        [Test]
        public void CreateShoppingCard_ShouldReturnInstanceOfShoppingCart_WhenInvoked()
        {
            var factory = new CosmeticsFactory();

            var execResult = factory.CreateShoppingCart();

            Assert.IsInstanceOf<IShoppingCart>(execResult);
        }

    }
}
