/***************************************************************************
 *                            QueuedMemoryWriter.cs
 *                            -------------------
 *   begin                : December 16, 2010
 *   copyright            : (C) The RunUO Software Team
 *   email                : info@runuo.com
 *
 *   $Id: QueuedMemoryWriter.cs 645 2010-12-23 11:36:25Z asayre $
 *
 ***************************************************************************/

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

namespace Server
{
	public sealed class QueuedMemoryWriter : BinaryFileWriter
	{
		private struct IndexInfo
		{
			public int size;
			public int typeCode;
			public int serial;
		}

		private MemoryStream _memStream;
		private List<IndexInfo> _orderedIndexInfo = new List<IndexInfo>();

		protected override int BufferSize
		{
			get { return 512; }
		}

		public QueuedMemoryWriter()
			: base(new MemoryStream(1024 * 1024), true)
		{
			this._memStream = this.UnderlyingStream as MemoryStream;
		}

		public void QueueForIndex(ISerializable serializable, int size)
		{
			IndexInfo info;

			info.size = size;

			info.typeCode = serializable.TypeReference;	//For guilds, this will automagically be zero.
			info.serial = serializable.SerialIdentity;

			_orderedIndexInfo.Add(info);
		}

		public void CommitTo(SequentialFileWriter dataFile, SequentialFileWriter indexFile)
		{
			this.Flush();

			int memLength = (int)_memStream.Position;

			if (memLength > 0)
			{
			byte[] memBuffer = _memStream.GetBuffer();

			long actualPosition = dataFile.Position;

			dataFile.Write(memBuffer, 0, memLength);	//The buffer contains the data from many items.

				//Console.WriteLine("Writing {0} bytes starting at {1}, with {2} things", memLength, actualPosition, _orderedIndexInfo.Count);

			byte[] indexBuffer = new byte[20];

				//int indexWritten = _orderedIndexInfo.Count * indexBuffer.Length;
			//int totalWritten = memLength + indexWritten

				for (int i = 0; i < _orderedIndexInfo.Count; i++)
			{
					IndexInfo info = _orderedIndexInfo[i];

				int typeCode = info.typeCode;
				int serial = info.serial;
				int length = info.size;


				indexBuffer[0] = (byte)(info.typeCode);
				indexBuffer[1] = (byte)(info.typeCode >> 8);
				indexBuffer[2] = (byte)(info.typeCode >> 16);
				indexBuffer[3] = (byte)(info.typeCode >> 24);

				indexBuffer[4] = (byte)(info.serial);
				indexBuffer[5] = (byte)(info.serial >> 8);
				indexBuffer[6] = (byte)(info.serial >> 16);
				indexBuffer[7] = (byte)(info.serial >> 24);

				indexBuffer[8] = (byte)(actualPosition);
				indexBuffer[9] = (byte)(actualPosition >> 8);
				indexBuffer[10] = (byte)(actualPosition >> 16);
				indexBuffer[11] = (byte)(actualPosition >> 24);
				indexBuffer[12] = (byte)(actualPosition >> 32);
				indexBuffer[13] = (byte)(actualPosition >> 40);
				indexBuffer[14] = (byte)(actualPosition >> 48);
				indexBuffer[15] = (byte)(actualPosition >> 56);

				indexBuffer[16] = (byte)(info.size);
				indexBuffer[17] = (byte)(info.size >> 8);
				indexBuffer[18] = (byte)(info.size >> 16);
				indexBuffer[19] = (byte)(info.size >> 24);

				indexFile.Write(indexBuffer, 0, indexBuffer.Length);

				actualPosition += info.size;
			}
			}

			this.Close();	//We're done with this writer.
		}
	}
}