using System;
using System.Collections.Generic;
using CurrencyExchangeLib;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace CurrencyExchangeTestLib
{
    [TestClass]
    public class CurrencyExchangeTest
    {
        const double DELTA = 0.000001;

        [TestMethod]
        public void Canary()
        {
            Assert.IsTrue(true);
        }

        [TestMethod]
        public void MarkDown()
        {
            var currencyExchange = new CurrencyExchange();
            Assert.AreEqual(98.0, currencyExchange.MarkDown(100), DELTA);
        }

        [TestMethod]
        public void GetRateNoVendors()
        {
            var currencyExchange = new CurrencyExchange();
            var result = new Tuple<String, double>("", 0.0);
            Assert.AreEqual(result, currencyExchange.GetRate("GBP"));
        }

        [TestMethod]
        public void GetRateWithOneVendor()
        {
            var vendorRateService = new CurrencyExchangeLib.Fakes.StubIVendorRateWebService()
            {
                GetExchangeStringString = (vendor, currency) => 100.0
            };

            var currencyExchange = new CurrencyExchange(vendorRateService);
            var result = new Tuple<string, double>("vendor1", 98.0);
            currencyExchange.SetVendors("vendor1");
            Assert.AreEqual(result, currencyExchange.GetRate("GBP"));
        }

        [TestMethod]
        public void GetRateWithOneVendorButServiceError()
        {
            var vendorRateService = new CurrencyExchangeLib.Fakes.StubIVendorRateWebService()
            {
                GetExchangeStringString = (vendor, currency) => { throw new ApplicationException("Error processing");} 
            };

            var currencyExchange = new CurrencyExchange(vendorRateService);
            var result = new Tuple<string, double>("", 0.0);
            currencyExchange.SetVendors("vendor1");
            Assert.AreEqual(result, currencyExchange.GetRate("GBP"));
        }

        [TestMethod]
        public void GetRateSecondVendorHighRate()
        {
            var rates = new Dictionary<string, double>() {{"vendor1", 10.0}, {"vendor2", 50.0}};
            var vendorRateService = new CurrencyExchangeLib.Fakes.StubIVendorRateWebService()
            {
                GetExchangeStringString = (vendor, currency) => rates[vendor]
            };

            var currencyExchange = new CurrencyExchange(vendorRateService);
            var result = new Tuple<string, double>("vendor2", 49.0);
            currencyExchange.SetVendors("vendor1", "vendor2");
            Assert.AreEqual(result, currencyExchange.GetRate("GBP"));
        }

        [TestMethod]
        public void GetRateFirstVendorHighRate()
        {
            var rates = new Dictionary<string, double>() { { "vendor1", 100.0 }, { "vendor2", 50.0 } };
            var vendorRateService = new CurrencyExchangeLib.Fakes.StubIVendorRateWebService()
            {
                GetExchangeStringString = (vendor, currency) => rates[vendor]
            };

            var currencyExchange = new CurrencyExchange(vendorRateService);
            var result = new Tuple<string, double>("vendor1", 98.0);
            currencyExchange.SetVendors("vendor1", "vendor2");
            Assert.AreEqual(result, currencyExchange.GetRate("GBP"));
        }

        [TestMethod]
        public void GetRateThreeVendors()
        {
            var rates = new Dictionary<string, double>() { { "vendor1", 10.0 }, { "vendor2", 50.0 }, {"vendor3", 50.0} };
            var vendorRateService = new CurrencyExchangeLib.Fakes.StubIVendorRateWebService()
            {
                GetExchangeStringString = (vendor, currency) => rates[vendor]
            };

            var currencyExchange = new CurrencyExchange(vendorRateService);
            var result = new Tuple<string, double>("vendor2", 49.0);
            currencyExchange.SetVendors("vendor1", "vendor2", "vendor3");
            Assert.AreEqual(result, currencyExchange.GetRate("GBP"));
        }

        [TestMethod]
        public void GetRateServiceFailForOneVendor()
        {
            var rates = new Dictionary<string, double>() { { "vendor1", 10.0 }, { "vendor2", 50.0 }, { "vendor3", 50.0 } };
            var vendorRateService = new CurrencyExchangeLib.Fakes.StubIVendorRateWebService()
            {
                GetExchangeStringString = (vendor, currency) => {
                    if (vendor == "vendor2") throw new ApplicationException("Simulate exception");
                    return rates[vendor];
                }
            };

            var currencyExchange = new CurrencyExchange(vendorRateService);
            var result = new Tuple<string, double>("vendor3", 49.0);
            currencyExchange.SetVendors("vendor1", "vendor2", "vendor3");
            Assert.AreEqual(result, currencyExchange.GetRate("GBP"));
        }
    }
}
