context: using System;
  using System.Collections.Generic;
  using WCell.RealmServer.Database.Entities;
  using WCell.Util.Logging;
  using WCell.Constants;
  using WCell.Constants.Items;
  using WCell.Core;
  using WCell.Core.Initialization;
  using WCell.RealmServer.Database;
  using WCell.RealmServer.Entities;
  using WCell.RealmServer.Global;
  using WCell.RealmServer.Handlers;
  using WCell.Util.Variables;
  using WCell.RealmServer.Network;
  using System.Threading;
  using System.Linq;
  
  namespace WCell.RealmServer.Mail
  {
  	public class MailMgr : Manager<MailMgr>
  	{
  		private static readonly Logger log = LogManager.GetCurrentClassLogger();
  
  		/// <summary>
  		/// Max number of items each player can store in their mailbox.
  		/// </summary>
  		public const int MaxItemsPerMail = 12;
  
  		public const int MaxMailSubjectLength = 128;	// based on ingame limitations
  
  		public const int MaxMailBodyLength = 512;	// based on ingame limitations
  
  		/// <summary>
  		/// Whether or not to delivery mail instantly for any type of mail.
  		/// </summary>
  		public static bool DeliverMailInstantly;
  
  		/// <summary>
  		/// Min delivery delay of mail with items or Gold in seconds (Default: 30 minutes)
  		/// </summary>
  		public static uint MinPacketDeliveryDelay = 30 * 60;
  		/// <summary>
  		/// Max delivery delay of mail with items or Gold in seconds (Default: 60 minutes)
  		/// </summary>
  		public static uint MaxPacketDeliveryDelay = 60 * 60;
  		/// <summary>
  		/// Max number of messages each player can store in their mailbox.
  		/// </summary>
  		public static uint MaxMailCount = 100;
  		/// <summary>
  		/// Max number of items each player can store in their mailbox.
  		/// </summary>
  		public static uint MaxStoredItems = 256;
  		/// <summary>
  		/// Max number of days to store regular mail in the mailbox.
  		/// </summary>
  		public static uint MailExpiryDelay = 30;
  		/// <summary>
  		/// Max number of days to store Cash-On_Delivery mail in the mailbox.
  		/// </summary>
  		public static uint MaxCODExpiryDelay = 3;
  		/// <summary>
  		/// Whether to allow characters to send mail to characters on the opposite Team.
  		/// </summary>
  		public static bool AllowInterFactionMail;
  		/// <summary>
  		/// The index of the item template to use for creating permanent mail storage.
  		/// </summary>
  		public static ItemId MailTextItemTemplate = ItemId.PlainLetter;
  
  		[Variable("ChargeMailPostage")]
  		public static bool ChargePostage = true;
  
  		/// <summary>
  		/// The amount of postage to charge per message sent, in copper.
  		/// </summary>
  		public static uint PostagePrice = 30;
  
  		#region Internal
  		#region Text Id Generator
  		private static bool _idGeneratorInitialised;
  		private static long _highestId;
  
  		private static void InitIdGenerator()
  		{
  			//long highestId;
  			try
  			{
  
  				MailMessage highestMailMessageItem = null;
  				highestMailMessageItem = RealmWorldDBMgr.DatabaseProvider.Session.QueryOver<MailMessage>().OrderBy(record => record.TextId).Desc.Take(1).SingleOrDefault();
  				var mailMessagehighestId = highestMailMessageItem != null ? highestMailMessageItem.TextId : 0;
  
  
  				//var mailMessagehighestId = RealmWorldDBMgr.DatabaseProvider.Query<MailMessage>().Max(mailMessage => mailMessage.TextId);
  
  				ItemRecord highestItemRecordItem = null;
  				highestItemRecordItem = RealmWorldDBMgr.DatabaseProvider.Session.QueryOver<ItemRecord>().OrderBy(record => record.ItemTextId).Desc.Take(1).SingleOrDefault();
  				var itemRecordHighestId = highestItemRecordItem != null ? highestItemRecordItem.ItemTextId : 0;
  
  
  				//var itemRecordHighestId = RealmWorldDBMgr.DatabaseProvider.Query<ItemRecord>().Max(itemRecord => itemRecord.ItemTextId);
  
  				_highestId = Math.Max(mailMessagehighestId, itemRecordHighestId);
  			}
  			catch (Exception e)
  			{
  				RealmWorldDBMgr.OnDBError(e);
  
  
  				MailMessage highestMailMessageItem = null;
  				highestMailMessageItem = RealmWorldDBMgr.DatabaseProvider.Session.QueryOver<MailMessage>().OrderBy(record => record.TextId).Desc.Take(1).SingleOrDefault();
  				var mailMessagehighestId = highestMailMessageItem != null ? highestMailMessageItem.TextId : 0;
  
  
  				//var mailMessagehighestId = RealmWorldDBMgr.DatabaseProvider.Query<MailMessage>().Max(mailMessage => mailMessage.TextId);
  
  
  				ItemRecord highestItemRecordItem = null;
  				highestItemRecordItem = RealmWorldDBMgr.DatabaseProvider.Session.QueryOver<ItemRecord>().OrderBy(record => record.ItemTextId).Desc.Take(1).SingleOrDefault();
  				var itemRecordHighestId = highestItemRecordItem != null ? highestItemRecordItem.ItemTextId : 0;
  
  
  				//var itemRecordHighestId = RealmWorldDBMgr.DatabaseProvider.Query<ItemRecord>().Max(itemRecord => itemRecord.ItemTextId);
  
  				_highestId = Math.Max(mailMessagehighestId, itemRecordHighestId);
  			}
  
  			//_highestId = (long)Convert.ChangeType(highestId, typeof(long));
  
  			_idGeneratorInitialised = true;
  		}
  
  		/// <summary>
  		/// Returns the next unique Id for a new Item
  		/// </summary>
  		public static long NextId()
  		{
  			if (!_idGeneratorInitialised)
  				InitIdGenerator();
  
  			return Interlocked.Increment(ref _highestId);
  		}
  
  		public static long LastId
  		{
  			get
  			{
  				if (!_idGeneratorInitialised)
  					InitIdGenerator();
  				return Interlocked.Read(ref _highestId);
  			}
  		}
  		#endregion
  		//internal static NHIdGenerator TextIdGenerator;
  
  		[Initialization(InitializationPass.Sixth)]	// init after NHIdGenerator init'ed (Fifth)
  		public static void Initialize()
  		{
  			try
  			{
  				CreateIdGenerators();
  			}
  			catch (Exception e)
  			{
  				RealmWorldDBMgr.OnDBError(e);
  				CreateIdGenerators();
  			}
  		}
  
  		private static void CreateIdGenerators()
  		{
  			//var mailIdGenerator = new NHIdGenerator(typeof(MailMessage), "_TextId");
  			//var itemTextIdGenerator = new NHIdGenerator(typeof(ItemRecord), "m_ItemTextId");
  			//if (LastId > LastItemRecordId)
  			//{
  			//	//TextIdGenerator = mailIdGenerator;
  			//}
  			//else
  			//{
  			//	//TextIdGenerator = itemTextIdGenerator;
  			//}
  		}
  
  		protected MailMgr()
  		{
  		}
  		#endregion
  
  		#region SendMail
  		public static bool SendMail(string recipientName, string subject, string body)
  		{
  			var id = CharacterRecord.GetIdByName(recipientName);
  			if (id <= 0)
  			{
  				return false;
  			}
  
  			SendMail(id, subject, body);
  			return true;
  		}
  
  		public static void SendMail(uint recipientLowId, string subject, string body)
  		{
  			var now = DateTime.Now;
  			var letter = new MailMessage(subject, body)
  			{
  				LastModifiedOn = null,
  				SenderId = 0,
  				ReceiverId = recipientLowId,
  				MessageStationary = MailStationary.Normal,
  				MessageType = MailType.Normal,
  				SendTime = now,
  				DeliveryTime = now
  			};
  
  			letter.Send();
  		}
  
  		public static MailError SendMail(string recipientName,
  										string subject,
  		                                 string body,
  		                                 MailStationary stationary,
  		                                 ICollection<ItemRecord> items,
  		                                 uint money,
  		                                 uint cod,
  		                                 IPacketReceiver sender)
  		{
  
gt: 			var id = CharacterRecord.GetIdByName(recipientName);