﻿using HelloWorld.Contracts.DataStores;
using HelloWorld.Contracts.Models;
using System;
using System.Collections.Generic;

namespace HelloWorld.MemoryDataStore
{
	public class MessageDataStore : IMessageDataStore
	{

		/// <summary>
		/// Dictionary containing all the created messages.  The id is the key.
		/// </summary>
		private static readonly IDictionary<int, Message> Messages = new Dictionary<int, Message>();

		/// <summary>
		/// Locking object to avoid multithreaded mayhem..
		/// </summary>
		private static Object MessagesLock = new Object();



		/// <summary>
		/// Simple implentation for an AutoInt
		/// </summary>
		private static int _autoId;

		/// <summary>
		/// Gets the next id while also implementing the _autoId by 1.
		/// </summary>
		/// <returns>The next Id to use</returns>
		private int GetNextId() => ++_autoId;


		/// <summary>
		/// Adds a new message to the backing dictionary
		/// </summary>
		/// <param name="data">The message to be added</param>
		/// <returns>The id of the newly created message</returns>
		public int Create(Message data)
		{
			lock (MessagesLock)
			{
				data.Id = GetNextId();
				Messages[data.Id] = data;
				return data.Id;
			}
		}


		/// <summary>
		/// Removes a message from the dictionary. If the message does not exist then nothing happens
		/// </summary>
		/// <param name="id">The id of the message to remove</param>
		public void Delete(int id)
		{
			lock (MessagesLock)
			{
				if (!Messages.ContainsKey(id))
					return;

				Messages.Remove(id);
			}
		}


		/// <summary>
		/// Retrieves a message from the dictionary.  If the message does not exist then null is returned.
		/// </summary>
		/// <param name="id">The id of the requested message</param>
		/// <returns></returns>
		public Message GetById(int id)
		{
			lock (MessagesLock)
			{
				if (!Messages.ContainsKey(id))
					return null;

				var message = Messages[id];
				return message;
			}
		}


		/// <summary>
		/// Updates a message in the dictionary. To do a key change just change the id in the data param.
		/// </summary>
		/// <param name="id">The id of the message to update</param>
		/// <param name="data">The new value of the message</param>
		public void Update(int id, Message data)
		{
			lock (MessagesLock)
			{
				if (!Messages.ContainsKey(id))
					throw new Exception($"The message with Id {id} was not found and could not be updated");

				//the request requires key change. Delete the current.
				if (data.Id != id)
				{
					Messages.Remove(id);
				}

				Messages[id] = data;
			}
		}
	}
}
