using System;
using System.Collections;


namespace DarkStrideToolbox
{
	public class DSBitArray
	{
		#region Properties
		private int m_nMaxIndexAllocated = 0;
		private int m_nMaxIndexUsed = -1;
		private BitArray m_oBits = null;
		#endregion


		public DSBitArray( int nLength )
		{
			m_nMaxIndexAllocated = DSMisc.Max( 10,nLength );
			m_oBits = new BitArray( m_nMaxIndexAllocated );			
		}


		public void Set( int nIndex,bool bValue )
		{
			if( nIndex >= m_nMaxIndexAllocated )
			{
				ReAllocate( m_nMaxIndexAllocated * 2 );
			}

			m_oBits[ nIndex ] = bValue;

			m_nMaxIndexUsed = DSMisc.Max( m_nMaxIndexUsed,nIndex );
		}
		public bool Get( int nIndex )
		{
			if( nIndex <= m_nMaxIndexUsed )
			{
				return( m_oBits[ nIndex ] );
			}
			else
			{
				return( false );
			}
		}

		public override string ToString()
		{
			string sRetVal = "";

			for( int i=0 ; i<=m_nMaxIndexUsed ; i++ )
			{
				if( Get( i ) == true )
				{
					sRetVal += "1";
				}
				else
				{
					sRetVal += "0";
				}
			}

			return( sRetVal );
		}


		public BitArray GetInternalBitArray()
		{
			BitArray oTempBits = GetBitArray( m_nMaxIndexUsed );
			return( oTempBits );
		}
		private void ReAllocate( int nNewMax )
		{
			m_oBits = GetBitArray( nNewMax );
			m_nMaxIndexAllocated = nNewMax;
			m_nMaxIndexUsed = DSMisc.Min( m_nMaxIndexUsed,nNewMax );
		}

		private BitArray GetBitArray( int nNewMax )
		{
			BitArray oTempBits = new BitArray( nNewMax );

			for( int i=0 ; i<=m_nMaxIndexUsed ; i++ )
			{
				if( i < nNewMax )
				{
					oTempBits[ i ] = m_oBits[ i ];
				}
			}

			return( oTempBits );
		}
		public void Insert( int nIndexToInsertAt,int nNumToInsert )
		{
			BitArray oTempBits = GetBitArray( m_nMaxIndexAllocated + nNumToInsert );

			for( int i=m_nMaxIndexUsed ; i>=nIndexToInsertAt ; i-- )
			{
				oTempBits[ i + nNumToInsert ] = oTempBits[ i ];
				if( i >= nIndexToInsertAt && i < nIndexToInsertAt + nNumToInsert )
				{
					oTempBits[ i ] = false;
				}
			}

			m_oBits = oTempBits;
			m_nMaxIndexAllocated = m_nMaxIndexAllocated + nNumToInsert;
			if( nIndexToInsertAt < m_nMaxIndexUsed )
			{
				m_nMaxIndexUsed += nNumToInsert;
			}
		}


		public static DSBitArray ConvertStringToBitArray( string sStringToConvert )
		{
			DSBitArray oRetVal = new DSBitArray( sStringToConvert.Length * 8 );
			long nValue = 0;
			char cChar = '0';


			for( int i=0 ; i<sStringToConvert.Length ; i++ )
			{
				cChar = sStringToConvert.ToCharArray( i,1 )[ 0 ];
				nValue = cChar;
				DSBitArray.ConvertIntToBitArray( oRetVal,i*8,8,nValue );
			}

			return( oRetVal );
		}
		public static string ConvertBitArrayToString( DSBitArray oValues )
		{
			string sRetVal = "";
			long nValue = 0;
			char cChar = '0';
		

			for( int i=0 ; i<oValues.Length ; i+=8 )
			{
				nValue = DSBitArray.ConvertBitArrayToInt( oValues,i,8 );
				cChar = Convert.ToChar( nValue );
				sRetVal += cChar.ToString();
			}


			return( sRetVal );
		}
		public static void ConvertIntToBitArray( DSBitArray oSerialized,int nStartPos,long nNumBytesToUse,long nValue )
		{
			long nTemp = nValue;
			int nPos = nStartPos;


			//Calculate how many didgets needed
			for( int i=0 ; i<nNumBytesToUse ; i++ )
			{
				oSerialized.Set( (int)nNumBytesToUse - i - 1 + nStartPos , ( ( nTemp & 1 ) == 1 ) );
				nTemp = nTemp >> 1;
			}
		}
		public static long ConvertBitArrayToInt( DSBitArray oSerialized,int nStartPos,long nNumBytesToUse )
		{
			long nTemp = 0;
			long nTotal = 0;


			//Calculate our value
			for( int nPos=(int)nNumBytesToUse ; nPos>0 ; nPos-- )
			{
				nTemp = 0;
				if( nPos+nStartPos-1 >= oSerialized.Length )
				{
					nTemp = 0;
				}
				else if( oSerialized.Get( nPos+nStartPos-1 ) == true )
				{
					nTemp = 1;
				}
				nTemp = nTemp << (int)(nNumBytesToUse - nPos);
				nTotal += nTemp;
			}


			return( nTotal );
		}

		public static int GetNumberOfBitsUsedIn( int nValue )
		{
			return( DSBitArray.GetNumberOfBitsUsedIn( (long)nValue ) );
		}
		public static int GetNumberOfBitsUsedIn( double nValue )
		{
			return( DSBitArray.GetNumberOfBitsUsedIn( (long)nValue ) );
		}
		public static int GetNumberOfBitsUsedIn( long nValue )
		{
			long nTemp = nValue;
			int nDidgetsUsed = 0;

			while( nTemp > 0 )
			{
				nTemp = nTemp >> 1;
				nDidgetsUsed++;
			}

			return( nDidgetsUsed );
		}



		#region Properties
		public int Length
		{
			get
			{
				return( m_nMaxIndexUsed + 1 );
			}
		}
		#endregion
	}
}
