// BarLayer.cpp : Implementation of cBarLayer
#include "stdafx.h"
#include "Inject.h"
#include "BarLayer.h"
#include "Manager.h"
#include "SimpleBar.h"

/////////////////////////////////////////////////////////////////////////////
// cBarLayer

// Drakier: Added constants for Panel and Radar size
const int RADAR_SIZE = 110;
const int PANEL_SIZE = 308;
const int VITALS_SIZE = 28;
const int CHATBAR_SIZE = 101;
const int CHATBAR_MAX_SIZE = 259;
const int LOOT_SIZE = 101;
const int BUTTON_SIZE = 16;
const int MINBAR_SIZE = 20;
int MAXBAR_SIZE = 100;

// Drakier: Added constants for docking position
const int DOCK_TOP = 0;
const int DOCK_LEFT = 1;
const int DOCK_RIGHT = 2;

enum eChildID
{
	eBtnForwards = 1,
	eBtnBackwards = 2,
	ePager = 3,
	eBtnMinMax = 4,
	eBtnDockCycle = 5,
	eChildBarFirst = 1000
};

cBarLayer::cBarLayer() : m_nBarStartPos( 0 ), m_nBarDock( DOCK_TOP ), m_nScreenWidth( 0 ), m_nScreenHeight( 0 ), m_nBarLength( 0 ), m_nPosition( 0 ), m_nDragging( 0 ), m_nMinMax( eStateMax )
{
}

void cBarLayer::onCreate()
{
	//::MessageBox( NULL, _T( "cBarLayer::onCreate" ), _T( "Inject.dll" ), MB_OK );
	m_pSite->get_PluginSite( &m_pPlugin );
	
	if (!cManager::_p->m_bContainer)
		m_pPlugin->get_Hooks( &m_pHooks );

	_ASSERTE( m_pPlugin.p != NULL );

	m_pPlugin->LoadBitmapPortal( 0x06001115, &m_pBackground );

	_ASSERTE( m_pBackground.p != NULL );

	RegKey key;
	key.Create( HKEY_LOCAL_MACHINE, _T( "SOFTWARE\\Decal" ) );

	DWORD dwAlpha = 255, dwRadarDraw = 1, dwBarDocked = 0;
	m_bRadarDraw = true;
	m_bDocked = false;

	if( key.QueryDWORDValue( "BarAlpha", dwAlpha ) == ERROR_SUCCESS )
		m_pSite->put_Alpha( dwAlpha );

	if( key.QueryDWORDValue( "BarRadarDraw", dwRadarDraw ) == ERROR_SUCCESS )
		m_bRadarDraw = dwRadarDraw ? true : false;

	if( key.QueryDWORDValue( "BarDocked", dwBarDocked ) == ERROR_SUCCESS )
		m_bDocked = (dwBarDocked == 1) ? true : false;

	if( key.QueryDWORDValue( "BarState", m_nMinMax ) != ERROR_SUCCESS )
		m_nMinMax = eStateMax;

	// Drakier: get the bar start pos or default to left
	if( key.QueryDWORDValue( "BarStart", (DWORD &)m_nBarStartPos ) != ERROR_SUCCESS )
		m_nBarStartPos = 0;

	// Drakier: get the bar length or default to 250 px
	if( key.QueryDWORDValue( "BarLength", (DWORD &)m_nBarLength ) != ERROR_SUCCESS )
		m_nBarLength = 250;

	// Drakier: get the bar dock setting (top/left/right) [default to top]
	if( key.QueryDWORDValue( "BarDock", (DWORD &)m_nBarDock ) != ERROR_SUCCESS )
		m_nBarDock = DOCK_TOP;

	// Drakier: TESTING for Min/Max Side Dock
	//if (m_nBarDock != DOCK_TOP)
		//m_nMinMax = eStateMin;

	// Ok, first create the 4 background controls
	LayerParams lpChild;
	lpChild.render = eRenderClipped;
	//= { eBtnMinMax, { 12, 3, 28, 19 }, eRenderClipped };
	{
		lpChild.ID = eBtnMinMax;
		CComPtr< ILayer > pUnk;
		HRESULT hRes = ::CoCreateInstance( CLSID_Button, NULL, CLSCTX_INPROC_SERVER, IID_ILayer, reinterpret_cast< void ** >( &pUnk ) );

		_ASSERTE( SUCCEEDED( hRes ) );

		m_pSite->CreateChild( &lpChild, pUnk );
		pUnk->QueryInterface( &m_pBtnMinMax );

		_ASSERTE( m_pBtnMinMax.p != NULL );

		m_pBtnMinMax->SetImages( 0, 0x0600113C, 0x0600113C );
		ICommandEventsImpl< BUTTON_MINMAX, cBarLayer >::advise( m_pBtnMinMax );
		m_pBtnMinMax->put_Matte( RGB( 0, 0, 0 ) );
	}

	{
		lpChild.ID = eBtnDockCycle;
		CComPtr< ILayer > pUnk;
		HRESULT hRes = ::CoCreateInstance( CLSID_Button, NULL, CLSCTX_INPROC_SERVER, IID_ILayer, reinterpret_cast< void ** >( &pUnk ) );

		_ASSERTE( SUCCEEDED( hRes ) );

		m_pSite->CreateChild( &lpChild, pUnk );
		pUnk->QueryInterface( & m_pBtnDockCycle );

		_ASSERTE ( m_pBtnDockCycle.p != NULL );

		m_pBtnDockCycle->SetImages( 0, 0x0600129A, 0x0600129B );
		ICommandEventsImpl< BUTTON_DOCKCYCLE, cBarLayer >::advise( m_pBtnDockCycle );
		m_pBtnDockCycle->put_Matte( RGB( 0, 0, 0 ) );
	}

	{
	  lpChild.ID = eBtnForwards;
	
		CComPtr< ILayer > pUnk;
		HRESULT hRes = ::CoCreateInstance( CLSID_Button, NULL, CLSCTX_INPROC_SERVER, IID_ILayer, reinterpret_cast< void ** >( &pUnk ) );

		_ASSERTE( SUCCEEDED( hRes ) );

		m_pSite->CreateChild( &lpChild, pUnk );
		pUnk->QueryInterface( &m_pBtnForwards );

		_ASSERTE( m_pBtnForwards.p != NULL );

		// Drakier: Bar Dock
		if (m_nBarDock != DOCK_TOP)
			m_pBtnForwards->SetImages( 0, 0x0600125E, 0x0600125F );
		else
			m_pBtnForwards->SetImages( 0, 0x06001298, 0x06001299 );
		ICommandEventsImpl< BUTTON_FORWARD, cBarLayer >::advise( m_pBtnForwards );
		m_pBtnForwards->put_Matte( RGB( 0, 0, 0 ) );
	}

	{
		lpChild.ID = eBtnBackwards;

		CComPtr< ILayer > pUnk;
		HRESULT hRes = ::CoCreateInstance( CLSID_Button, NULL, CLSCTX_INPROC_SERVER, IID_ILayer, reinterpret_cast< void ** >( &pUnk ) );

		_ASSERTE( SUCCEEDED( hRes ) );

		m_pSite->CreateChild( &lpChild, pUnk );
		pUnk->QueryInterface( &m_pBtnBackwards );

		_ASSERTE( m_pBtnBackwards.p != NULL );

		// Drakier: Bar Dock
		if (m_nBarDock != DOCK_TOP)
			m_pBtnBackwards->SetImages( 0, 0x06001261, 0x06001262 );
		else
			m_pBtnBackwards->SetImages( 0, 0x06001295, 0x06001296 );
		ICommandEventsImpl< BUTTON_BACK, cBarLayer >::advise( m_pBtnBackwards );
		m_pBtnBackwards->put_Matte( RGB( 0, 0, 0 ) );
	}

	{
		lpChild.ID = ePager;

		CComPtr< ILayer > pUnk;
		HRESULT hRes = ::CoCreateInstance( CLSID_Pager, NULL, CLSCTX_INPROC_SERVER, IID_ILayer, reinterpret_cast< void ** >( &pUnk ) );

		_ASSERTE( SUCCEEDED( hRes ) );

		m_pSite->CreateChild( &lpChild, pUnk );
		pUnk->QueryInterface( &m_pPager );

		_ASSERTE( m_pPager.p != NULL );

		IPagerEventsImpl< PAGER_CLIENT, cBarLayer >::advise( m_pPager );
	}

	m_pSite->put_Transparent( VARIANT_FALSE );

	if( m_nMinMax == eStateMin )
		m_pBtnMinMax->SetImages( 0, 0x0600113C, 0x0600113C );
	else
		m_pBtnMinMax->SetImages( 0, 0x0600113B, 0x0600113B );
	
	//::MessageBox( NULL, _T( "Here" ), _T( "[Inject.dll] cBarLayer::onCreate" ), MB_OK );
}

void cBarLayer::onDestroy()
{
	m_pHooks.Release();
	m_pPlugin.Release();
	m_pBtnForwards.Release();
	m_pBtnBackwards.Release();
	m_pBackground.Release();
	m_pPager.Release();
}

STDMETHODIMP cBarLayer::Render(ICanvas *pCanvas)
{
	_ASSERTE( pCanvas != NULL );

	SIZE sz;
	m_pPlugin->GetScreenSize( &sz );	
	if ( sz.cx <= 1024 ) 
		MAXBAR_SIZE = 80;
	else
		MAXBAR_SIZE = 100;

	ClipParams p;
	pCanvas->GetClipParams( &p );

	m_pBackground->PatBlt( pCanvas, &p.window, &p.org );

	if (m_nBarDock == DOCK_TOP) // if we are top docked
	{
		RECT dragBarRect;
		dragBarRect.left = 3;
		dragBarRect.top = 4;
		dragBarRect.right = 4;
		dragBarRect.bottom = 19;

		pCanvas->Fill(&dragBarRect, RGB(214, 173, 140));
		
		dragBarRect.left += 1;
		dragBarRect.right += 1;
		pCanvas->Fill(&dragBarRect, RGB(165, 82, 57));

		dragBarRect.left += 2;
		dragBarRect.right += 2;
		pCanvas->Fill(&dragBarRect, RGB(214, 173, 140));

		dragBarRect.left += 1;
		dragBarRect.right += 1;
		pCanvas->Fill(&dragBarRect, RGB(165, 82, 57));

		// Drakier: draw the right-hand grab bars
		dragBarRect.left = m_nBarLength - 4;
		dragBarRect.top = 4;
		dragBarRect.right = m_nBarLength - 3;
		dragBarRect.bottom = 19;

		pCanvas->Fill(&dragBarRect, RGB(165, 82, 57));

		dragBarRect.left -= 1;
		dragBarRect.right -= 1;
		pCanvas->Fill(&dragBarRect, RGB(214, 173, 140));

		dragBarRect.left -= 2;
		dragBarRect.right -= 2;
		pCanvas->Fill(&dragBarRect, RGB(165, 82, 57));

		dragBarRect.left -= 1;
		dragBarRect.right -= 1;
		pCanvas->Fill(&dragBarRect, RGB(214, 173, 140));
	}
	else // draw on the sides
	{
		RECT dragBarRect;
		dragBarRect.top = 3;
		dragBarRect.left = 4;
		dragBarRect.bottom = 4;
		if (m_nMinMax == eStateMin) // Minimized
			dragBarRect.right = MINBAR_SIZE - 4;
		else // Maximized
			dragBarRect.right = MAXBAR_SIZE - 4;

		pCanvas->Fill(&dragBarRect, RGB(214, 173, 140));
		
		dragBarRect.top += 1;
		dragBarRect.bottom += 1;
		pCanvas->Fill(&dragBarRect, RGB(165, 82, 57));

		dragBarRect.top += 2;
		dragBarRect.bottom += 2;
		pCanvas->Fill(&dragBarRect, RGB(214, 173, 140));

		dragBarRect.top += 1;
		dragBarRect.bottom += 1;
		pCanvas->Fill(&dragBarRect, RGB(165, 82, 57));

		// Drakier: draw the right-hand grab bars
		dragBarRect.top = m_nBarLength - 4;
		dragBarRect.left = 4;
		dragBarRect.bottom = m_nBarLength - 3;
		if (m_nMinMax == eStateMin) // Minimized
			dragBarRect.right = MINBAR_SIZE - 4;
		else // Maximized
			dragBarRect.right = MAXBAR_SIZE - 4;

		pCanvas->Fill(&dragBarRect, RGB(165, 82, 57));

		dragBarRect.top -= 1;
		dragBarRect.bottom -= 1;
		pCanvas->Fill(&dragBarRect, RGB(214, 173, 140));

		dragBarRect.top -= 2;
		dragBarRect.bottom -= 2;
		pCanvas->Fill(&dragBarRect, RGB(165, 82, 57));

		dragBarRect.top -= 1;
		dragBarRect.bottom -= 1;
		pCanvas->Fill(&dragBarRect, RGB(214, 173, 140));
	}

	_ASSERTMEM( _CrtCheckMemory( ) );

	return S_OK;
}

#define ENUM_REFORMAT	1
class cBarEnumFormat
{
public:
	long nCursor;
};

STDMETHODIMP cBarLayer::Reformat()
{
	_ASSERTE( m_pSite.p != NULL );

	//::MessageBox( NULL, _T( "cBarLayer::reformat" ), _T( "Inject.dll" ), MB_OK );

	SIZE sz;
	m_pPlugin->GetScreenSize( &sz );
	long lX = sz.cx, lY = sz.cy;
	HRESULT hW = S_FALSE, hH = S_FALSE;

	// Drakier: if we are not in the container, get the 3D Area
	if ( !cManager::_p->m_bContainer )
	{
		hH = m_pHooks->get_Area3DHeight( &lY );
		hW = m_pHooks->get_Area3DWidth( &lX );
	}

	// Drakier: if we are in the container, or the 3D area's are NULL
	if ( (cManager::_p->m_bContainer) || (hW != S_OK) || (hH != S_OK) )
	{
		m_nScreenWidth = sz.cx - PANEL_SIZE;
		m_nScreenHeight = sz.cy;
	}
	else // Drakier: If everything comes out right and we are not in container
	{
		if( (hW == S_OK) &&  (lX > 200) && (lX < 2000) )
			m_nScreenWidth = lX;
		if( (hH == S_OK) && (lY > 200) && (lY < 2000) )
			m_nScreenHeight = lY;
	}

	// Drakier: set up the bar position
	// Drakier: make sure bar isn't off of left side of screen
	//          and that the bar length is at least 112 px
	if (m_nBarStartPos < 0)
		m_nBarStartPos = 0;
	if (m_nBarLength < 112)
		m_nBarLength = 250;
	// Drakier: the right edge of the 3D area is (m_nScreenWidth)
	//          If you include the radar (110) it is (m_nScreenWidth - RADAR_SIZE)

	// Drakier: need 2 of these sections. One for top dock and one for side dock
	// Drakier: TOP DOCK
	if (m_nBarDock == DOCK_TOP)
	{
		// make sure bar isn't off RIGHT side of screen
		if (m_nBarLength > m_nScreenWidth )
			m_nBarLength = m_nScreenWidth;

		// Drakier: adjust bar start position so its not offscreen
		if (m_nBarStartPos > m_nScreenWidth )
			m_nBarStartPos = m_nScreenWidth - m_nBarLength;

		// Drakier: Adjust for Panel
		if ((m_nBarStartPos + m_nBarLength) > m_nScreenWidth )
			m_nBarLength = m_nScreenWidth - m_nBarStartPos;

		// Drakier: Adjust for Radar
		if ( (!m_bRadarDraw) && ((m_nBarStartPos + m_nBarLength) > (m_nScreenWidth - RADAR_SIZE)) )
			m_nBarLength = m_nScreenWidth - RADAR_SIZE - m_nBarStartPos;
	}
	else
	{
		// Drakier: SIDE DOCK
		// Check the Right Side if Radar is on!
		if ( ( !m_bRadarDraw ) && ( m_nBarDock == DOCK_RIGHT ) && ( m_nBarStartPos < RADAR_SIZE ) )
			m_nBarStartPos = RADAR_SIZE;
		
		if ( cManager::_p->m_bContainer ) // Drakier: In container (use CONST sizes)
		{
			// Drakier: make sure bar isn't off BOTTOM of screen
			if (m_nBarLength > (m_nScreenHeight - (VITALS_SIZE + CHATBAR_SIZE + LOOT_SIZE)) )
				m_nBarLength = (m_nScreenHeight - (VITALS_SIZE + CHATBAR_SIZE + LOOT_SIZE));

			// Drakier: adjust bar start position so its not offscreen
			if (m_nBarStartPos > (m_nScreenHeight - (VITALS_SIZE + CHATBAR_SIZE + LOOT_SIZE)) )
				m_nBarStartPos = (m_nScreenHeight - (VITALS_SIZE + CHATBAR_SIZE + LOOT_SIZE)) - m_nBarLength;

			// Drakier: Adjust for Panels
			if ((m_nBarStartPos + m_nBarLength) > (m_nScreenHeight - (VITALS_SIZE + CHATBAR_SIZE + LOOT_SIZE)) )
				m_nBarLength = (m_nScreenHeight - (VITALS_SIZE + CHATBAR_SIZE + LOOT_SIZE)) - m_nBarStartPos;
		}
		else // Drakier: Not in container
		{
			// Drakier: make sure bar isn't off BOTTOM of screen
			if (m_nBarLength > m_nScreenHeight )
				m_nBarLength = m_nScreenHeight;

			// Drakier: Adjust for Panels
			if ((m_nBarStartPos + m_nBarLength) > m_nScreenHeight )
				m_nBarLength = m_nScreenHeight - m_nBarStartPos;

			// Drakier: adjust bar start position so its not offscreen
			if (m_nBarStartPos > m_nScreenHeight)
				m_nBarStartPos = m_nScreenHeight - m_nBarLength;

			// Drakier: if Docked (within 10 px) then stretch to fit
			if ( m_bDocked )
				m_nBarLength = m_nScreenHeight - m_nBarStartPos;
		}
	}

	// Drakier: Draw the bar
	RECT rc;
	if (m_nBarDock == DOCK_LEFT) // Left Dock
	{
		rc.left = 0;
		rc.top = m_nBarStartPos;
		rc.bottom = m_nBarStartPos + m_nBarLength;
		if (m_nMinMax == eStateMin) // Minimized
			rc.right = MINBAR_SIZE;
		else // Maximized
			rc.right = MAXBAR_SIZE;
	}
	else if (m_nBarDock == DOCK_RIGHT) // Right Dock
	{
		if (m_nMinMax == eStateMin) // Minimized
			rc.left = m_nScreenWidth - MINBAR_SIZE;
		else // Maximized
			rc.left = m_nScreenWidth - MAXBAR_SIZE;
	
		rc.top = m_nBarStartPos;
		rc.right = m_nScreenWidth;
		rc.bottom = m_nBarStartPos + m_nBarLength;
	}
	else // Top Dock
	{
		rc.left = m_nBarStartPos;
		rc.top = 0;
		rc.right = m_nBarStartPos + m_nBarLength;
		rc.bottom = 23;
	}
	m_pSite->put_Position( &rc );

	// Now do the MinMax button
	// { 12, 3, 28, 19 }
	if (m_nBarDock != DOCK_TOP) // Side Dock
	{
		if ( (m_nBarDock == DOCK_LEFT) || (m_nMinMax == eStateMin) )
		{
			rc.left = 3;
			rc.top = 12;
			rc.right = rc.left + BUTTON_SIZE;
			rc.bottom = rc.top + BUTTON_SIZE;	
		}
		else // Right Dock
		{
			rc.left = MAXBAR_SIZE - ( BUTTON_SIZE + 3 );
			rc.top = 12;
			rc.right = rc.left + BUTTON_SIZE;
			rc.bottom = rc.top + BUTTON_SIZE;
		}
	}
	else // Top Dock
	{
		rc.left = 12;
		rc.top = 3;
		rc.right = rc.left + BUTTON_SIZE;
		rc.bottom = rc.top + BUTTON_SIZE;
	}
	CComPtr< ILayerSite > pMinMaxSite;
	m_pSite->get_Child( eBtnMinMax, ePositionByID, &pMinMaxSite );
	pMinMaxSite->put_Position( &rc );
	
	// Now do the dock cycle
	if (m_nBarDock != DOCK_TOP) // Side Dock
	{		
		if (m_nMinMax == eStateMin) // minimized
		{
			rc.left = 3;
			rc.top = m_nBarLength - 28;
			rc.right = rc.left + BUTTON_SIZE;
			rc.bottom = rc.top + BUTTON_SIZE;
		}
		else
		{
			if (m_nBarDock == DOCK_LEFT)
			{
				rc.left = MAXBAR_SIZE - ( BUTTON_SIZE + 3 );
				rc.top = 12;
				rc.right = rc.left + BUTTON_SIZE;
				rc.bottom = rc.top + BUTTON_SIZE;
			}
			else
			{
				rc.left = 3;
				rc.top = 12;
				rc.right = rc.left + BUTTON_SIZE;
				rc.bottom = rc.top + BUTTON_SIZE;	
			}
		}
	}
	else // Top Dock
	{
		rc.left = m_nBarLength - 28;
		rc.top = 3;
		rc.right = rc.left + BUTTON_SIZE;
		rc.bottom = rc.top + BUTTON_SIZE;
	}
	CComPtr< ILayerSite > pDockCycleSite;
	m_pSite->get_Child( eBtnDockCycle, ePositionByID, &pDockCycleSite );
	pDockCycleSite->put_Position( &rc );
   
	// Now the pager
   	CComPtr< ILayerSite > pPagerSite;
	m_pSite->get_Child( ePager, ePositionByID, &pPagerSite );   
   		
	m_offsets.clear();
	long nChildren;	
	long nOffset = 0;
	long nDesired;
	pPagerSite->get_ChildCount( &nChildren );
	
	for( long nChild = 0; nChild < nChildren; ++ nChild )
	{
		ViewParams pParams;
		CComPtr< ILayerSite > pChildSite;
		pPagerSite->get_Child( nChild, ePositionByIndex, &pChildSite );

		long nChildID;
		pChildSite->get_ID( &nChildID );

		if( nChildID < eChildBarFirst )
			continue;

		CComPtr< ISimpleBar > pBarNative;
		pChildSite->GetSink( IID_ISimpleBar, reinterpret_cast< void ** >( &pBarNative ) );

		pBarNative->get_Params(&pParams);
		pParams.state = m_nMinMax;
		pBarNative->put_Params(&pParams);

		if (m_nBarDock != DOCK_TOP) // Side Dock
		{         
			if (m_nMinMax == eStateMin) // Minimized
			{				
				rc.right = MINBAR_SIZE - 2; 
			}
			else // Maximized
			{
				rc.right = MAXBAR_SIZE - 2;
			}
			nDesired = 20; // Button Height
			rc.left = 0;
			rc.top = nOffset;         
			rc.bottom = nOffset + nDesired;
		}
		else // Top Dock
		{
			// We always give bars their desired size (Width)
			pBarNative->get_RenderWidth( &nDesired );
			rc.left = nOffset;
			rc.top = 0;
			rc.right = nOffset + nDesired;
			rc.bottom = 21;
		}
		pChildSite->put_Position( &rc );

		m_offsets.push_back( nOffset );
		nOffset += nDesired + 2;
	}

	// Calc ViewSlots for SideDock Maximized Up/Down Visibility	
	long nTotalBtnHeight;	  
	// nOffset is total button height
	nTotalBtnHeight = nOffset;

	bool showPosBtns;   	
	//showPosBtns = (nTotalBtnHeight > m_nBarLength);

	if (m_nBarDock != DOCK_TOP) // Side Dock
	{
		rc.left = 1;
		if (m_nMinMax == eStateMin) // minimized
		{			
			showPosBtns = ( nTotalBtnHeight > ( m_nBarLength - 58 ) ); // Viewable Height
			if ( showPosBtns )
			{
				rc.top = 50;
				rc.bottom = m_nBarLength - 48;
			}
			else
			{
				rc.top = 30;
				rc.bottom = m_nBarLength - 28;
			}
			rc.right = MINBAR_SIZE - 1;						
		} 
		else  // maximized
		{
			showPosBtns = ( nTotalBtnHeight > ( m_nBarLength - 44 ) ); // Viewable Height
			rc.top = 30;
			rc.right = MAXBAR_SIZE - 1;
			rc.bottom = m_nBarLength - 12;			
		}
	}
	else // Top Dock
	{
		showPosBtns = ( nTotalBtnHeight > ( m_nBarLength - 58 ) ); //Max Viewable Width		
		if ( showPosBtns )
		{
			rc.left = 50;
			rc.right = m_nBarLength - 48;
		}
		else
		{
			rc.left = 30;
			rc.right = m_nBarLength - 28;
		}		
		rc.top = 1;		
		rc.bottom = 22;		
	}
	pPagerSite->put_Position( &rc );
	
	// Now do the backwards
	if ( showPosBtns ) 
	{
		if (m_nBarDock != DOCK_TOP) // Side Dock
		{
			if (m_nMinMax == eStateMin) // minimized
			{
				rc.left = 3;
				rc.top = 30;
				rc.right = rc.left + BUTTON_SIZE;
				rc.bottom = rc.top + BUTTON_SIZE;
			}
			else
			{
				rc.top = 12;				
				rc.left = (MAXBAR_SIZE / 2) - 17;            
				rc.right = rc.left + BUTTON_SIZE;
				rc.bottom = rc.top + BUTTON_SIZE;	   
			}		
		}
		else // Top Dock
		{
			rc.left = 30;
			rc.top = 3;
			rc.right = rc.left + BUTTON_SIZE;
			rc.bottom = rc.top + BUTTON_SIZE;
		}
	}
	else
	{
		rc.left = -30;
		rc.top = -30;
		rc.right = rc.left + BUTTON_SIZE;
		rc.bottom = rc.top + BUTTON_SIZE;
	}
	CComPtr< ILayerSite > pBackwardsSite;
	m_pSite->get_Child( eBtnBackwards, ePositionByID, &pBackwardsSite );
	pBackwardsSite->put_Position( &rc );

	// Drakier: this is a change because of the new LENGTH system

	// Now do the forwards
	if ( showPosBtns ) 
	{
		if (m_nBarDock != DOCK_TOP) // Side Dock
		{		
			if (m_nMinMax == eStateMin) // minimized
			{
				rc.left = 3;
				rc.top = m_nBarLength - 46;
				rc.right = rc.left + BUTTON_SIZE;
				rc.bottom = rc.top + BUTTON_SIZE;
			}
			else
			{         
				rc.top = 12;						   
				rc.left = (MAXBAR_SIZE / 2) + 1;         
				rc.right = rc.left + BUTTON_SIZE;
				rc.bottom = rc.top + BUTTON_SIZE;
			}
		}
		else // Top Dock
		{
			rc.left = m_nBarLength - 46;
			rc.top = 3;
			rc.right = rc.left + BUTTON_SIZE;
			rc.bottom = rc.top + BUTTON_SIZE;
		}
	}
	else
	{
		rc.left = -30;
		rc.top = -30;
		rc.right = rc.left + BUTTON_SIZE;
		rc.bottom = rc.top + BUTTON_SIZE;
	}
	CComPtr< ILayerSite > pFwdSite;
	m_pSite->get_Child( eBtnForwards, ePositionByID, &pFwdSite );
	pFwdSite->put_Position( &rc );

	/* Drakier: Testing if un-needed
	// Check if the position is wrong now
	if( m_nPosition >= m_offsets.size() )
		m_nPosition = m_offsets.size() - 1;
	*/
	if ( !showPosBtns ) 
		m_nPosition = 0;

	POINT pt = { ( m_nPosition <= 0 ) ? 0 : m_offsets[ m_nPosition ], 0 };

	if (m_nBarDock != DOCK_TOP) // Side Dock
	{
		pt.x =  0;
		pt.y = ( m_nPosition <= 0 ) ? 0 : m_offsets[ m_nPosition ];
	}
	else // Top Dock
	{
		pt.x = ( m_nPosition <= 0 ) ? 0 : m_offsets[ m_nPosition ];
		pt.y = 0;
	}

	m_pPager->ScrollTo( &pt );
	m_pSite->Invalidate();

	return S_OK;
}

VARIANT_BOOL cBarLayer::onClientGetNextPosition(long nID, long nCommand, long *pnX, long *pnY)
{
	switch( nCommand )
	{
	case eBtnForwards:
		if (m_nBarDock != DOCK_TOP) // Side Dock
		{
			if( !m_bLocked && ( m_offsets.size() > 0 ) && ( ( m_nPosition + 1 ) <  m_offsets.size() ) )
			{
				m_bLocked = TRUE;
				m_nPosition++;
				*pnX = 0;
				*pnY = m_offsets[ m_nPosition ];

				return VARIANT_TRUE;
			}
		}
		else // Top Dock
		{
			if( !m_bLocked && ( m_offsets.size() > 0 ) && ( ( m_nPosition + 1 ) < m_offsets.size() ) )
			{
				//m_bLocked = TRUE;
				m_nPosition++;
				*pnX = m_offsets[ m_nPosition ];
				*pnY = 0;

				return VARIANT_TRUE;
			}
		}
		break;

	case eBtnBackwards:
		if (m_nBarDock != DOCK_TOP) // Side Dock
		{
			if( !m_bLocked && m_nPosition > 0 )
			{
				m_bLocked = TRUE;
				m_nPosition--;
				*pnX = 0;
				*pnY = m_offsets[ m_nPosition ];

				return VARIANT_TRUE;
			}
		}
		else // Top Dock
		{
			if( !m_bLocked && m_nPosition > 0 )
			{
				//m_bLocked = TRUE;
				m_nPosition--;
				*pnX = m_offsets[ m_nPosition ];
				*pnY = 0;

				return VARIANT_TRUE;
			}
		}
		break;
		
	default:
		// Unknown command
		_ASSERT( FALSE );
	}

	// Unknown command or over/underflow - end paging
	return VARIANT_FALSE;
}

STDMETHODIMP cBarLayer::AddBar(long nViewID, ViewParams *pParams)
{
	_ASSERTE( pParams != NULL );
	_ASSERTE( pParams->label != NULL );

	CComObject< cSimpleBar > *pNewBar;
	CComObject< cSimpleBar >::CreateInstance( &pNewBar );

	pNewBar->put_Params( pParams );

	CComPtr< ILayerSite > pPagerSite;
	m_pSite->get_Child( ePager, ePositionByID, &pPagerSite );
	
	LayerParams p = { nViewID, { 0, 0, 0, 0 }, eRenderClipped };

	pPagerSite->CreateChild( &p, pNewBar );

	m_pSite->Reformat();

	return S_OK;
}

STDMETHODIMP cBarLayer::RemoveBar(long nViewID)
{
	CComPtr< ILayerSite > pPagerSite;
	m_pSite->get_Child( ePager, ePositionByID, &pPagerSite );

	CComPtr< ILayerSite > pBarSite;
	HRESULT hRes = pPagerSite->get_Child( nViewID, ePositionByID, &pBarSite );

	if( FAILED( hRes ) )
		// Probably not found
		return hRes;

	m_pSite->Reformat();

	return pBarSite->Destroy();
}

STDMETHODIMP cBarLayer::get_Bar(long nViewID, ViewParams *pVal)
{
	CComPtr< ILayerSite > pPagerSite;
	m_pSite->get_Child( ePager, ePositionByID, &pPagerSite );

	CComPtr< ILayerSite > pBarSite;
	HRESULT hRes = pPagerSite->get_Child( nViewID, ePositionByID, &pBarSite );

	if( FAILED( hRes ) )
		// Probably not found
		return hRes;

	CComPtr< ISimpleBar > pSimpleBar;
	pBarSite->GetSink( IID_ISimpleBar, reinterpret_cast< void ** >( &pSimpleBar ) );

	pSimpleBar->get_Params( pVal );

	return S_OK;
}

STDMETHODIMP cBarLayer::put_Bar(long nViewID, ViewParams *newVal)
{
	CComPtr< ILayerSite > pPagerSite;
	m_pSite->get_Child( ePager, ePositionByID, &pPagerSite );

	CComPtr< ILayerSite > pBarSite;
	HRESULT hRes = pPagerSite->get_Child( nViewID, ePositionByID, &pBarSite );

	if( FAILED( hRes ) )
		// Probably not found
		return hRes;

	CComPtr< ISimpleBar > pSimpleBar;
	pBarSite->GetSink( IID_ISimpleBar, reinterpret_cast< void ** >( &pSimpleBar ) );

	pSimpleBar->put_Params( newVal );

	m_pSite->Reformat();

	return S_OK;
}

void __stdcall cBarLayer::onMinMaxHit(long nID) {
	RegKey key;

	if (m_nMinMax == eStateMax)
	{
		m_nMinMax = eStateMin;
		m_pBtnMinMax->SetImages(0, 0x0600113C, 0x0600113C);
	}
	else
	{
		m_nMinMax = eStateMax;
		m_pBtnMinMax->SetImages(0, 0x0600113B, 0x0600113B);
	}

	key.Create(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Decal"));
	key.SetDWORDValue("BarState", m_nMinMax);

	Reformat();
}

void __stdcall cBarLayer::onDockCycleHit(long nID) {
	RegKey key;
	key.Create(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Decal"));

	m_nBarDock = (m_nBarDock + 1) % 3;

	if (m_nBarDock != DOCK_TOP)
	{
		m_pBtnForwards->SetImages( 0, 0x0600125E, 0x0600125F );
		m_pBtnBackwards->SetImages( 0, 0x06001261, 0x06001262 );
		//m_nMinMax = eStateMin;
		if( key.QueryDWORDValue( "BarState", m_nMinMax ) != ERROR_SUCCESS )
			m_nMinMax = eStateMax;
	}
	else
	{
		m_pBtnForwards->SetImages( 0, 0x06001298, 0x06001299 );
		m_pBtnBackwards->SetImages( 0, 0x06001295, 0x06001296 );
		if( key.QueryDWORDValue( "BarState", m_nMinMax ) != ERROR_SUCCESS )
			m_nMinMax = eStateMax;
	}

	key.SetDWORDValue("BarDock", m_nBarDock);

	m_pPager->FinishCommand;
	Reformat();
}

STDMETHODIMP cBarLayer::MouseEvent(long nMsg, long wParam, long lParam) {
	switch (nMsg)
	{
	case WM_LBUTTONDOWN:
		RECT rSize;
		m_pSite->get_Position(&rSize);

		POINTS pt;
		pt = MAKEPOINTS(lParam);
		
		if( !cManager::_p->m_bContainer )
			pt.y -= 28;
		
		if (m_nBarDock != DOCK_TOP) // Side Dock
		{
			m_bDocked = FALSE;
			// Drakier: Grabbing the Top drag bar
			if (pt.x >= rSize.left && pt.x <= rSize.right && pt.y >= rSize.top + 1 && pt.y <= rSize.top + 8)
			{
				m_nDragging = -1;
				m_DeltaY = pt.y;
			}

			// Drakier: Grabbing the right drag bar
			if (pt.x >= rSize.left && pt.x <= rSize.right && pt.y >= rSize.bottom - 8 && pt.y <= rSize.bottom - 1)
			{
				m_nDragging = 1;
				m_DeltaY = pt.y;
			}			
		}
		else // Top Dock
		{
			// Drakier: Grabbing the left drag bar
			if (pt.y >= rSize.top && pt.y <= rSize.bottom && pt.x >= rSize.left + 1 && pt.x <= rSize.left + 8)
			{
				m_nDragging = -1;
				m_DeltaX = pt.x;
			}

			// Drakier: Grabbing the right drag bar
			if (pt.y >= rSize.top && pt.y <= rSize.bottom && pt.x >= rSize.right - 8 && pt.x <= rSize.right - 1)
			{
				m_nDragging = 1;
				m_DeltaX = pt.x;
			}
		}
		break;

	case WM_LBUTTONUP:
		if( m_nDragging == -1 || m_nDragging == 1 )
		{
			m_nDragging = 0;

			RegKey key;
			key.Create(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Decal"));
			// Drakier: For the new bar system
			key.SetDWORDValue("BarStart", (DWORD)m_nBarStartPos);
			key.SetDWORDValue("BarLength", (DWORD)m_nBarLength);

			if ( m_nBarDock != DOCK_TOP ) // Drakier: Side Docked
			{
				// Drakier: should we keep the decal bar STUCK to bottom of screen?
				if ( (m_nBarStartPos + m_nBarLength) > (m_nScreenHeight - 10) )
					m_bDocked = TRUE;
				else
					m_bDocked = FALSE;

				key.SetDWORDValue("BarDocked", (DWORD)m_bDocked);
				Reformat();
			}
		}
		break;

	case WM_MOUSEMOVE:
		if (m_nBarDock != DOCK_TOP) // Side Dock
		{
			if ( m_nDragging == -1 ) // Drakier: Drag Up
			{
				POINTS pt;
				pt = MAKEPOINTS(lParam);
				
				if( !cManager::_p->m_bContainer )
					pt.y -= 28;

				if ( !m_bRadarDraw ) // Drakier: Radar On?
				{
					if ( ((m_nBarLength - (pt.y - m_DeltaY)) > 112 ) && (((pt.y - m_DeltaY) + m_nBarStartPos) >= 0) && (((pt.y - m_DeltaY) + m_nBarStartPos) >= (RADAR_SIZE)) )
					{
						m_nBarStartPos += pt.y - m_DeltaY;
						m_nBarLength += (-1) * (pt.y - m_DeltaY);
						m_DeltaY = pt.y;
					}

				}
				else
				{
					if ( ((m_nBarLength - (pt.y - m_DeltaY)) > 112 ) && (((pt.y - m_DeltaY) + m_nBarStartPos) >= 0) )
					{
						m_nBarStartPos += pt.y - m_DeltaY;
						m_nBarLength += (-1) * (pt.y - m_DeltaY);
						m_DeltaY = pt.y;
					}
				}

				Reformat( );
			}
			else if ( m_nDragging == 1 ) // Drakier: Drag Down
			{
				POINTS pt;
				pt = MAKEPOINTS(lParam);
				
				if( !cManager::_p->m_bContainer )
					pt.y -= 28;

				if ( cManager::_p->m_bContainer )
				{
					if ( ((pt.y - m_DeltaY + m_nBarLength) >= 112) && ((m_nBarStartPos + m_nBarLength + pt.y - m_DeltaY) <= (m_nScreenHeight - (VITALS_SIZE + CHATBAR_SIZE + LOOT_SIZE))) )
					{
						m_nBarLength += pt.y - m_DeltaY;
						m_DeltaY = pt.y;
					}
				}
				else
				{
					if ( ((pt.y - m_DeltaY + m_nBarLength) >= 112) && ((m_nBarStartPos + m_nBarLength + pt.y - m_DeltaY) <= m_nScreenHeight) )
					{
						m_nBarLength += pt.y - m_DeltaY;
						m_DeltaY = pt.y;
					}
				}
				Reformat( );
			}
		}
		else // Top Dock
		{
			if ( m_nDragging == -1 ) // Drakier: Drag Left
			{
				POINTS pt;
				pt = MAKEPOINTS(lParam);
				
				if( !cManager::_p->m_bContainer )
					pt.y -= 28;

				if ( ((m_nBarLength - (pt.x - m_DeltaX)) > 112 ) && (((pt.x - m_DeltaX) + m_nBarStartPos) >= 0) )
				{
					m_nBarStartPos += pt.x - m_DeltaX;
					m_nBarLength += (-1) * (pt.x - m_DeltaX);
					m_DeltaX = pt.x;
				}

				Reformat( );
			}
			else if ( m_nDragging == 1 ) // Drakier: Drag Right
			{
				POINTS pt;
				pt = MAKEPOINTS(lParam);
				
				if( !cManager::_p->m_bContainer )
					pt.y -= 28;
				if ( !m_bRadarDraw ) // Drakier: Radar on?
				{
					//if ( ((pt.x - m_DeltaX + m_nBarLength) >= 112) && ((m_nBarStartPos + m_nBarLength + pt.x - m_DeltaX) <= (*m_p3DW - RADAR_SIZE)) )
					if ( ((pt.x - m_DeltaX + m_nBarLength) >= 112) && ((m_nBarStartPos + m_nBarLength + pt.x - m_DeltaX) <= (m_nScreenWidth - RADAR_SIZE)) )
					{
						m_nBarLength += pt.x - m_DeltaX;
						m_DeltaX = pt.x;
					}
				}
				else // Drakier: Radar off!
				{
					if ( ((pt.x - m_DeltaX + m_nBarLength) >= 112) && ((m_nBarStartPos + m_nBarLength + pt.x - m_DeltaX) <= m_nScreenWidth) )
					{
						m_nBarLength += pt.x - m_DeltaX;
						m_DeltaX = pt.x;
					}
				}

				Reformat( );
			}
		}
		break;
	}
	return S_OK;
}