﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Silk.Mapping.Tests
{
	[TestClass]
	public class InterchangableEnumerableTests
	{
		private readonly IServiceCollection _serviceCollection = new ServiceCollection();
		private readonly IServiceProvider _serviceProvider;
		private readonly IObjectMapper _mapper;

		public InterchangableEnumerableTests()
		{
			_serviceCollection.AddSilkMappingServices();
			_serviceProvider = _serviceCollection.BuildServiceProvider();
			_mapper = _serviceProvider.GetRequiredService<IObjectMapper>();
		}

		[TestMethod]
		public void ShallowCopyFromListToArray()
		{
			var source = new ClassWithList
			{
				Property = new List<string>()
				{
					"Hello", "World"
				}
			};
			var mapped = _mapper.Map<ClassWithArray>(source);
			Assert.AreEqual(source.Property.Count, mapped.Property.Length);
			for (var i = 0; i < source.Property.Count; i++)
				Assert.AreEqual(source.Property[i], mapped.Property[i]);
		}

		[TestMethod]
		public void ShallowCopyFromArrayToList()
		{
			var source = new ClassWithArray
			{
				Property = new string[]
				{
					"Hello", "World"
				}
			};
			var mapped = _mapper.Map<ClassWithList>(source);
			Assert.AreEqual(source.Property.Length, mapped.Property.Count);
			for (var i = 0; i < source.Property.Length; i++)
				Assert.AreEqual(source.Property[i], mapped.Property[i]);
		}

		[TestMethod]
		public void ShallowCopyFromEnumerableToList()
		{
			var source = new ClassWithEnumerable
			{
				Property = EnumerableSource
			};
			var mapped = _mapper.Map<ClassWithList>(source);
			Assert.AreEqual(source.Property.Count(), mapped.Property.Count);
			var i = 0;
			foreach (var item in source.Property)
				Assert.AreEqual(mapped.Property[i++], item);
		}

		[TestMethod]
		public void ShallowCopyFromListToEnumerable()
		{
			var source = new ClassWithList
			{
				Property = new List<string>()
				{
					"Hello", "World"
				}
			};
			var mapped = _mapper.Map<ClassWithEnumerable>(source);
			Assert.AreEqual(source.Property.Count, mapped.Property.Count());
			var i = 0;
			foreach (var item in mapped.Property)
				Assert.AreEqual(source.Property[i++], item);
		}

		[TestMethod]
		public void ShallowCopyFromEnumerableToArray()
		{
			var source = new ClassWithEnumerable
			{
				Property = EnumerableSource
			};
			var mapped = _mapper.Map<ClassWithArray>(source);
			Assert.AreEqual(source.Property.Count(), mapped.Property.Length);
			var i = 0;
			foreach (var item in source.Property)
				Assert.AreEqual(mapped.Property[i++], item);
		}

		[TestMethod]
		public void ShallowCopyFromArrayToEnumerable()
		{
			var source = new ClassWithArray
			{
				Property = new string[]
				{
					"Hello", "World"
				}
			};
			var mapped = _mapper.Map<ClassWithEnumerable>(source);
			Assert.AreEqual(source.Property.Length, mapped.Property.Count());
			var i = 0;
			foreach (var item in mapped.Property)
				Assert.AreEqual(source.Property[i++], item);
		}

		private IEnumerable<string> EnumerableSource
		{
			get
			{
				yield return "Hello";
				yield return "World";
			}
		}

		private class ClassWithEnumerable
		{
			public IEnumerable<string> Property { get; set; }
		}

		private class ClassWithList
		{
			public List<string> Property { get; set; }
		}

		private class ClassWithArray
		{
			public string[] Property { get; set; }
		}
	}
}
