
#include "Gwen/Gwen.h"
#include "Gwen/Controls/CrossSplitter.h"
#include "Gwen/Controls/Button.h"

using namespace Gwen;
using namespace Controls;

GWEN_CONTROL_CONSTRUCTOR( CrossSplitter )
{
	m_VSplitter = new SplitterBar( this );
	m_VSplitter->SetPos( 0, 128 );
	m_VSplitter->onDragged.Add( this, &CrossSplitter::OnVerticalMoved );
	m_VSplitter->SetCursor( Gwen::CursorType::SizeNS );

	m_HSplitter = new SplitterBar( this );
	m_HSplitter->SetPos( 128, 0 );
	m_HSplitter->onDragged.Add( this, &CrossSplitter::OnHorizontalMoved );
	m_HSplitter->SetCursor( Gwen::CursorType::SizeWE );

	m_CSplitter = new SplitterBar( this );
	m_CSplitter->SetPos( 128, 128 );
	m_CSplitter->onDragged.Add( this, &CrossSplitter::OnCenterMoved );
	m_CSplitter->SetCursor( Gwen::CursorType::SizeAll );

	m_fHVal = 0.5f;
	m_fVVal = 0.5f;

	SetPanel( 0, NULL );
	SetPanel( 1, NULL );
	SetPanel( 2, NULL );
	SetPanel( 3, NULL );

	SetSplitterSize( 5 );

	m_iZoomedSection = -1;
}

void CrossSplitter::UpdateVSplitter()
{
	m_VSplitter->MoveTo( m_VSplitter->X(), ( Height() - m_VSplitter->Height() ) * ( m_fVVal ));
}
void CrossSplitter::UpdateHSplitter()
{
	m_HSplitter->MoveTo( ( Width() - m_HSplitter->Width() ) * ( m_fHVal ), m_HSplitter->Y() );
}

void CrossSplitter::OnCenterMoved( Controls::Base * /*control*/ )
{ 
	//Move the other two bars into position
	CalculateValueCenter();
	Invalidate();
}

void CrossSplitter::UpdateCSplitter()
{
	m_CSplitter->MoveTo( ( Width() - m_CSplitter->Width() ) * ( m_fHVal ), ( Height() - m_CSplitter->Height() ) * ( m_fVVal ));
}

void CrossSplitter::OnHorizontalMoved( Controls::Base * /*control*/ )
{ 
	m_fHVal = CalculateValueHorizontal();
	Invalidate();
}
void CrossSplitter::OnVerticalMoved( Controls::Base * /*control*/ )
{
	m_fVVal = CalculateValueVertical();	
	Invalidate();
}

void CrossSplitter::CalculateValueCenter()
{
	m_fHVal = (float)m_CSplitter->X() / (float)( Width() - m_CSplitter->Width() );
	m_fVVal = (float)m_CSplitter->Y() / (float)( Height() - m_CSplitter->Height() );
}

float CrossSplitter::CalculateValueHorizontal()
{
	return  (float)m_HSplitter->X() / (float)( Width() - m_HSplitter->Width() );
}

float CrossSplitter::CalculateValueVertical()
{
	return  (float)m_VSplitter->Y() / (float)( Height() - m_VSplitter->Height() );
}

void CrossSplitter::Layout( Skin::Base* /*skin*/ )
{
	m_VSplitter->SetSize( Width(), m_fBarSize );
	m_HSplitter->SetSize( m_fBarSize, Height() );
	m_CSplitter->SetSize( m_fBarSize, m_fBarSize );

	UpdateVSplitter();
	UpdateHSplitter();
	UpdateCSplitter();

	if (	m_iZoomedSection == -1 )
	{
		if ( m_Sections[0] )
			m_Sections[0]->SetBounds( 0, 0, m_HSplitter->X(), m_VSplitter->Y() );

		if ( m_Sections[1] )
			m_Sections[1]->SetBounds( m_HSplitter->X() + m_fBarSize, 0, Width() - ( m_HSplitter->X() + m_fBarSize ), m_VSplitter->Y() );

		if ( m_Sections[2] )
			m_Sections[2]->SetBounds( 0, m_VSplitter->Y() + m_fBarSize, m_HSplitter->X(), Height() - ( m_VSplitter->Y() + m_fBarSize ) );

		if ( m_Sections[3] )
			m_Sections[3]->SetBounds( m_HSplitter->X() + m_fBarSize, m_VSplitter->Y() + m_fBarSize, Width() - ( m_HSplitter->X() + m_fBarSize ), Height() - ( m_VSplitter->Y() + m_fBarSize ) );
	}
	else
	{
		//This should probably use Fill docking instead
		m_Sections[m_iZoomedSection]->SetBounds( 0, 0, Width(), Height() );
	}
}

void CrossSplitter::SetPanel( int index, Controls::Base* pPanel)
{
	Debug::AssertCheck( index >= 0 && index <= 3, "CrossSplitter::SetPanel out of range" );

	m_Sections[index] = pPanel;

	if ( pPanel )
	{
		pPanel->Dock( Pos::None );
		pPanel->SetParent( this );
	}

	Invalidate();
}

Controls::Base* CrossSplitter::GetPanel( int i )
{
	return m_Sections[i];
}


void CrossSplitter::ZoomChanged()
{
	onZoomChange.Call( this );
	if ( m_iZoomedSection == -1 )
	{
		onUnZoomed.Call( this );
	}
	else
	{
		onZoomed.Call( this );
	}
}

void CrossSplitter::Zoom( int section )
{
	UnZoom();

	if ( m_Sections[section] )
	{
		for (int i = 0; i < 4; i++)
		{
			if ( i != section && m_Sections[i] )
				m_Sections[i]->SetHidden( true );
		}
		m_iZoomedSection = section;

		Invalidate();
	}
	ZoomChanged();
}

void CrossSplitter::UnZoom()
{
	m_iZoomedSection = -1;

	for ( int i = 0; i < 4; i++ )
	{
		if ( m_Sections[i] )
			m_Sections[i]->SetHidden( false );
	}

	Invalidate();
	ZoomChanged();
}