// MultiLinkTypeIn.cpp : implementation file
//

#include "stdafx.h"
#include "demopaja.h"
#include "DemopajaDoc.h"
#include "MultiLinkTypeIn.h"

using namespace PajaTypes;
using namespace Composition;
using namespace Import;
using namespace PluginClass;
using namespace PajaSystem;



// CMultiLinkTypeIn dialog

IMPLEMENT_DYNAMIC(CMultiLinkTypeIn, CDialog)
CMultiLinkTypeIn::CMultiLinkTypeIn(CWnd* pParent /*=NULL*/)
	: CDialog(CMultiLinkTypeIn::IDD, pParent)
	, m_sInfoText(_T(""))
	, m_iCurSel( -1 )
{
}

CMultiLinkTypeIn::~CMultiLinkTypeIn()
{
}

void CMultiLinkTypeIn::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LISTLINKS, m_ListLinks);
	DDX_Control(pDX, IDC_BUTTONADD, m_ButtonAdd);
	DDX_Control(pDX, IDC_BUTTONDEL, m_ButtonDel);
	DDX_Control(pDX, IDC_BUTTONUP, m_ButtonUp);
	DDX_Control(pDX, IDC_BUTTONDOWN, m_ButtonDown);
	DDX_Control(pDX, IDOK, m_ButtonOk);
	DDX_Control(pDX, IDCANCEL, m_ButtonCancel);
	DDX_Text(pDX, IDC_INFO, m_sInfoText);
	DDX_Control(pDX, IDC_COMBO1, m_ComboLinks);
}


BEGIN_MESSAGE_MAP(CMultiLinkTypeIn, CDialog)
	ON_BN_CLICKED(IDC_BUTTONADD, OnBnClickedButtonadd)
	ON_BN_CLICKED(IDC_BUTTONDEL, OnBnClickedButtondel)
	ON_BN_CLICKED(IDC_BUTTONUP, OnBnClickedButtonup)
	ON_BN_CLICKED(IDC_BUTTONDOWN, OnBnClickedButtondown)
	ON_NOTIFY(NM_CLICK, IDC_LISTLINKS, OnNMClickListlinks)
	ON_CBN_SELCHANGE(IDC_COMBO1, OnCbnSelchangeCombo1)
END_MESSAGE_MAP()


// CMultiLinkTypeIn message handlers

void CMultiLinkTypeIn::OnBnClickedButtonadd()
{
	CDemopajaDoc*	pDoc = GetDoc();
	ASSERT_VALID( pDoc );

	pDoc->BeginDeferHandleParamNotify();

	// Add new empty link
	pDoc->HandleParamNotify( m_pParam->add_link( 0 ) );

	UpdateLinkList();

	// Set selected item
	int	nItems = m_ListLinks.GetItemCount();
	m_ListLinks.SetItemState( nItems - 1, LVIS_SELECTED, LVIS_SELECTED );
	UpdateSelection();

	pDoc->EndDeferHandleParamNotify();

	pDoc->NotifyViews( NOTIFY_REDRAW_GRAPHICS );
}

void CMultiLinkTypeIn::OnBnClickedButtondel()
{
	CDemopajaDoc*	pDoc = GetDoc();
	ASSERT_VALID( pDoc );

	pDoc->BeginDeferHandleParamNotify();

	int	iListSel = -1;
	POSITION pos = m_ListLinks.GetFirstSelectedItemPosition();
	if( pos )
		iListSel = m_ListLinks.GetNextSelectedItem(pos);

	// Find currently selected link.
	if( iListSel == -1 )
		return;
	int	iCurLink = m_ListLinks.GetItemData( iListSel );

	// Delet link
	m_pParam->del_link( iCurLink );

	// Delete item.
	UpdateLinkList();
	UpdateSelection();

	pDoc->EndDeferHandleParamNotify();

	pDoc->NotifyViews( NOTIFY_REDRAW_GRAPHICS );
}

void CMultiLinkTypeIn::OnBnClickedButtonup()
{
	CDemopajaDoc*	pDoc = GetDoc();
	ASSERT_VALID( pDoc );

	pDoc->BeginDeferHandleParamNotify();

	int	iListSel = -1;
	POSITION pos = m_ListLinks.GetFirstSelectedItemPosition();
	if( pos )
		iListSel = m_ListLinks.GetNextSelectedItem(pos);

	// Find currently selected link.
	if( iListSel == -1 )
		return;
	int	iCurLink = m_ListLinks.GetItemData( iListSel );

	int	iTargetLink = iCurLink - 1;

	if( iTargetLink < 0 )
		return;

	EffectI*	pEffect = m_pParam->get_link( iCurLink );

	// Delete link
	m_pParam->del_link( iCurLink );

	// Insert new link
	m_pParam->insert_link( iTargetLink, pEffect );

	// Delete item.
	UpdateLinkList();

	// Set selected item
	m_ListLinks.SetItemState( iTargetLink, LVIS_SELECTED, LVIS_SELECTED );

	UpdateSelection();

	pDoc->EndDeferHandleParamNotify();

	pDoc->NotifyViews( NOTIFY_REDRAW_GRAPHICS );
}

void CMultiLinkTypeIn::OnBnClickedButtondown()
{
	CDemopajaDoc*	pDoc = GetDoc();
	ASSERT_VALID( pDoc );

	pDoc->BeginDeferHandleParamNotify();

	int	iListSel = -1;
	POSITION pos = m_ListLinks.GetFirstSelectedItemPosition();
	if( pos )
		iListSel = m_ListLinks.GetNextSelectedItem(pos);

	// Find currently selected link.
	if( iListSel == -1 )
		return;
	int	iCurLink = m_ListLinks.GetItemData( iListSel );

	int	iTargetLink = iCurLink + 1;

	if( iTargetLink >= m_pParam->get_link_count() )
		return;

	EffectI*	pEffect = m_pParam->get_link( iCurLink );

	// Delete link
	m_pParam->del_link( iCurLink );

	// Insert new link
	m_pParam->insert_link( iTargetLink, pEffect );

	// Delete item.
	UpdateLinkList();

	// Set selected item
	m_ListLinks.SetItemState( iTargetLink, LVIS_SELECTED, LVIS_SELECTED );

	UpdateSelection();

	pDoc->EndDeferHandleParamNotify();

	pDoc->NotifyViews( NOTIFY_REDRAW_GRAPHICS );
}

BOOL CMultiLinkTypeIn::OnInitDialog()
{
	CDialog::OnInitDialog();

	// map colors
	COLORMAP	rColors[3];
	// magenta BG
	rColors[0].from = RGB( 255, 0, 255 );
	rColors[0].to = ::GetSysColor( COLOR_BTNFACE );
	// light grey
	rColors[1].from = RGB( 192, 192, 192 );
	rColors[1].to = ::GetSysColor( COLOR_BTNFACE );
	// dark grey
	rColors[2].from = RGB( 128, 128, 128 );
	rColors[2].to = ::GetSysColor( COLOR_BTNSHADOW );

	// create bitmaps for buttons
	if( !m_rBitmapAdd.LoadMappedBitmap( IDB_LINK_ADD, 0, rColors, 3 ) )
		return -1;
	if( !m_rBitmapDel.LoadMappedBitmap( IDB_LINK_DEL, 0, rColors, 3 ) )
		return -1;
	if( !m_rBitmapUp.LoadMappedBitmap( IDB_LINK_UP, 0, rColors, 3 ) )
		return -1;
	if( !m_rBitmapDown.LoadMappedBitmap( IDB_LINK_DOWN, 0, rColors, 3 ) )
		return -1;

	m_ButtonAdd.SetBitmaps( m_rBitmapAdd );
	m_ButtonDel.SetBitmaps( m_rBitmapDel );
	m_ButtonUp.SetBitmaps( m_rBitmapUp );
	m_ButtonDown.SetBitmaps( m_rBitmapDown );
	
	m_ButtonAdd.SetTooltipText( "Add New Link" );
	m_ButtonDel.SetTooltipText( "Delete Link" );
	m_ButtonUp.SetTooltipText( "Move Link Up" );
	m_ButtonDown.SetTooltipText( "Move Link Down" );
	
	m_ButtonOk.SetFlat( FALSE );
	m_ButtonCancel.SetFlat( FALSE );

	m_ListLinks.InsertColumn( 0, "Links", LVCFMT_LEFT, 180 );

	UpdateLinkList();

	return TRUE;
}

void CMultiLinkTypeIn::OnOK()
{

	CDialog::OnOK();
}

void CMultiLinkTypeIn::OnNMClickListlinks(NMHDR *pNMHDR, LRESULT *pResult)
{
	UpdateSelection();
	*pResult = 0;
}

void CMultiLinkTypeIn::OnCbnSelchangeCombo1()
{
	// Change effect
	int	iListSel = -1;
	POSITION pos = m_ListLinks.GetFirstSelectedItemPosition();
	if( pos )
		iListSel = m_ListLinks.GetNextSelectedItem(pos);

	// Find currently selected link.
	if( iListSel == -1 )
		return;
	int	iCurLink = m_ListLinks.GetItemData( iListSel );

	CDemopajaDoc*	pDoc = GetDoc();
	ASSERT_VALID( pDoc );

	EffectI*	pEffect = 0;
	int				iComboSel = m_ComboLinks.GetCurSel();
	if( iComboSel != CB_ERR )
	{
		int	iNum = m_ComboLinks.GetItemData( iComboSel );
		if( iNum != CB_ERR && iNum != 0xffffffff )
			pEffect = m_pLayer->get_effect( iNum );
	}

	pDoc->BeginDeferHandleParamNotify();

	// Set link
	pDoc->HandleParamNotify( m_pParam->set_link( iCurLink, pEffect ) );

	// Update list text
	UpdateLinkList();

	// Set selected item
	m_ListLinks.SetItemState( iCurLink, LVIS_SELECTED, LVIS_SELECTED );

	pDoc->EndDeferHandleParamNotify();

	pDoc->NotifyViews( NOTIFY_REDRAW_GRAPHICS );
}

void
CMultiLinkTypeIn::UpdateLinkList()
{
	// Empty the list.
	m_ListLinks.DeleteAllItems();

	// Add links
	for( uint32 i = 0; i < m_pParam->get_link_count(); i++ ) {
		EffectI*	pEffect = m_pParam->get_link( i );
		if( pEffect )
		{
			int	nItem = m_ListLinks.InsertItem( i, pEffect->get_name() );
			m_ListLinks.SetItemData( nItem, i );
		}
		else
		{
			int	nItem = m_ListLinks.InsertItem( i, "<Unlinked>" );
			m_ListLinks.SetItemData( nItem, i );
		}
 	}
}

void
CMultiLinkTypeIn::UpdateSelection()
{
	int	iSel = -1;
	POSITION pos = m_ListLinks.GetFirstSelectedItemPosition();
	if( pos )
		iSel = m_ListLinks.GetNextSelectedItem(pos);

	// Reset combo before filling it.
	m_ComboLinks.ResetContent();

	if( iSel != -1 )
	{
		if( iSel == m_iCurSel )
			return;

		// Fill combo box with correct effects.
		int	iCurLink = m_ListLinks.GetItemData( iSel );

		// Add all 
		std::string	sStr;
		int32		i32Idx;
		int32		i32Sel = 0;

		EffectI*	pParamEffect = 0;

		if( m_pParam->get_link_count() )
		{
			pParamEffect = m_pParam->get_link( iCurLink );
		}


		if( pParamEffect )
			TRACE( "pParamEffect = %s\n", pParamEffect->get_name() );
		else
			TRACE( "could not find selected effect: %d\n", iCurLink );

		// Add unlinking
		i32Idx = m_ComboLinks.AddString( "<Unlinked>" );
		m_ComboLinks.SetItemData( i32Idx, 0xffffffff );

		bool	bCanAdd = false;

		for( int32 i = 0; i < m_pLayer->get_effect_count(); i++ ) {
			
			EffectI*	pEffect = m_pLayer->get_effect( i );

			// Skip null effects and self
			if( !pEffect )
			{
				continue;
			}

			// Dont allow to link to effects that are evaluated after the current effect.
			if( pEffect == m_pEffect )
			{
				bCanAdd = true;
				continue;
			}

			if( bCanAdd )
			{
				if( (m_pParam->get_class_filter() == NULL_CLASSID ||
					m_pParam->get_class_filter() == pEffect->get_class_id()) &&
					(m_pParam->get_super_class_filter() == NULL_SUPERCLASS ||
					m_pParam->get_super_class_filter() == pEffect->get_super_class_id()) ) {

					i32Idx = m_ComboLinks.AddString( pEffect->get_name() );
					m_ComboLinks.SetItemData( i32Idx, i );
				}

				if( pParamEffect == pEffect )
				{
					i32Sel = i32Idx;
				}
			}
		}

		m_ComboLinks.SetCurSel( i32Sel );
	}

	m_iCurSel = iSel;
}
