//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $NoKeywords: $
//=============================================================================//
#include "client_pch.h"
#include "cl_demoeditorpanel.h"
#include "cl_demoactionmanager.h"
#include "cl_demoaction.h"
#include <vgui_controls/Button.h>
#include <vgui_controls/CheckButton.h>
#include <vgui_controls/Label.h>

#include <vgui_controls/Controls.h>
#include <vgui/ISystem.h>
#include <vgui/ISurface.h>
#include <vgui_controls/PropertySheet.h>
#include <vgui/IVGui.h>
#include <vgui_controls/FileOpenDialog.h>
#include <vgui_controls/ProgressBar.h>
#include <vgui_controls/ListPanel.h>
#include <vgui_controls/MenuButton.h>
#include <vgui_controls/Menu.h>
#include "cl_demoactioneditors.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

using namespace vgui;

// So new actions can have sequential/unique names
static int g_nNewActionNumber = 1;

//-----------------------------------------------------------------------------
// Purpose: A menu button that knows how to parse cvar/command menu data from gamedir\scripts\debugmenu.txt
//-----------------------------------------------------------------------------
class CNewActionButton : public vgui::MenuButton
{
	typedef vgui::MenuButton BaseClass;

public:
	// Construction
	CNewActionButton( vgui::Panel *parent, const char *panelName, const char *text );

private:
	// Menu associated with this button
	Menu	*m_pMenu;
};

//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CNewActionButton::CNewActionButton(Panel *parent, const char *panelName, const char *text)
	: BaseClass( parent, panelName, text )
{
	// Assume no menu
	m_pMenu = new Menu( this, "DemoEditNewAction" );

	int count = NUM_DEMO_ACTIONS;
	int i;
	for ( i = 1 ; i < count; i++ )
	{
		char const *actionType = CBaseDemoAction::NameForType( (DEMOACTION)i );

		m_pMenu->AddMenuItem( actionType, actionType, parent );
		m_pMenu->SetItemEnabled( actionType, CBaseDemoAction::HasEditorFactory( (DEMOACTION)i ) );
	}
	
	m_pMenu->MakePopup();
	MenuButton::SetMenu(m_pMenu);
	SetOpenDirection(Menu::UP);
}

//-----------------------------------------------------------------------------
// Purpose: Basic help dialog
//-----------------------------------------------------------------------------
CDemoEditorPanel::CDemoEditorPanel( vgui::Panel *parent ) : Frame( parent, "DemoEditorPanel")
{
	int w = 440;
	int h = 300;

	SetSize( w, h );

	SetTitle("Demo Editor", true);

	m_pSave = new vgui::Button( this, "DemoEditSave", "Save" );
	m_pRevert = new vgui::Button( this, "DemoEditRevert", "Revert" );;
	m_pOK = new vgui::Button( this, "DemoEditOk", "OK" );
	m_pCancel = new vgui::Button( this, "DemoEditCancel", "Cancel" );

	m_pNew = new CNewActionButton( this, "DemoEditNew", "New->" );
	m_pEdit = new vgui::Button( this, "DemoEditEdit", "Edit..." );
	m_pDelete = new vgui::Button( this, "DemoEditDelete", "Delete" );

	m_pCurrentDemo = new vgui::Label( this, "DemoName", "" );

	m_pActions = new vgui::ListPanel( this, "DemoActionList" );

	vgui::ivgui()->AddTickSignal( GetVPanel(), 0 );

	LoadControlSettings("Resource\\DemoEditorPanel.res");

	int xpos, ypos;
	parent->GetPos( xpos, ypos );
	ypos += parent->GetTall();

	SetPos( xpos, ypos );

	m_pActions->AddColumnHeader(0, "actionname", "Action", m_pActions->GetWide() / 3);
	m_pActions->AddColumnHeader(1, "actiontype", "Type", m_pActions->GetWide() / 3);
	m_pActions->AddColumnHeader(2, "actionstart", "Start", m_pActions->GetWide() / 3);
	OnRefresh();

	SetVisible( true );
	SetSizeable( false );
	SetMoveable( true );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CDemoEditorPanel::~CDemoEditorPanel()
{
}

void CDemoEditorPanel::OnTick()
{
	BaseClass::OnTick();

	m_pCurrentDemo->SetText( demoaction->GetCurrentDemoFile() );
	bool hasdemo = demoaction->GetCurrentDemoFile()[0] ? true : false;

	if ( !hasdemo )
	{
		m_pNew->SetEnabled( false );
		m_pEdit->SetEnabled( false );
		m_pDelete->SetEnabled( false );
		m_pSave->SetEnabled( false );
		m_pRevert->SetEnabled( false );

	}
	else
	{
		m_pNew->SetEnabled( true );
		
		int count = demoaction->GetActionCount();

		m_pEdit->SetEnabled( count > 0 );
		m_pDelete->SetEnabled( count > 0 );

		if ( m_pActions && m_pActions->GetSelectedItemsCount() != 1 )
		{
			m_pEdit->SetEnabled( false );
			m_pDelete->SetEnabled( false );
		}

		m_pSave->SetEnabled( demoaction->IsDirty() );
		m_pRevert->SetEnabled( demoaction->IsDirty() );
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *command - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CDemoEditorPanel::IsNewActionCommand( char const *command )
{
	DEMOACTION type = CBaseDemoAction::TypeForName( command );
	if ( type != DEMO_ACTION_UNKNOWN )
	{
		return true;
	}
	return false;
}

//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *actiontype - 
//-----------------------------------------------------------------------------
void CDemoEditorPanel::CreateNewAction( char const *actiontype )
{
	if ( m_hCurrentEditor != 0 )
		return;

	DEMOACTION type = CBaseDemoAction::TypeForName( actiontype );
	if ( type == DEMO_ACTION_UNKNOWN )
		return;
	
	CBaseDemoAction *action = CBaseDemoAction::CreateDemoAction( type );
	if ( action )
	{
		action->SetActionName( va( "Unnamed%i", g_nNewActionNumber++ ) );
		demoaction->SetDirty( true );

		m_hCurrentEditor = CBaseDemoAction::CreateActionEditor( action->GetType(), this, action, true );
		if ( m_hCurrentEditor != 0 )
		{
			m_hCurrentEditor->SetVisible( true );
			m_hCurrentEditor->SetSize( 400, 300 );
		}
	}
}


//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *command - 
//-----------------------------------------------------------------------------
void CDemoEditorPanel::OnCommand(const char *command)
{
	if ( !Q_strcasecmp( command, "edit" ) )
	{
		OnEdit();
	}
	else if ( !Q_strcasecmp( command, "delete" ) )
	{
		OnDelete();
	}
	else if ( !Q_strcasecmp( command, "save" ) )
	{
		OnSave();
	}
	else if ( !Q_strcasecmp( command, "Close" ) )
	{
		OnSave();
		MarkForDeletion();
		OnClose();
	}
	else if ( !Q_strcasecmp( command, "cancel" ) )
	{
		OnRevert();
		MarkForDeletion();
		OnClose();
	}
	else if ( !Q_strcasecmp( command, "revert" ) )
	{
		OnRevert();
	}
	else if ( IsNewActionCommand( command ) )
	{
		CreateNewAction( command );
	}
	else
	{
		BaseClass::OnCommand( command );
	}
}

void CDemoEditorPanel::OnVDMChanged( void )
{
	OnRefresh();
}

void CDemoEditorPanel::PurgeActionList()
{
	if ( !m_pActions )
	{
		Assert( 0 );
		return;
	}

	m_pActions->DeleteAllItems();
}

void CDemoEditorPanel::PopulateActionList()
{
	PurgeActionList();

	int count = demoaction->GetActionCount();
	int i;
	for ( i = 0; i < count; i++ )
	{
		CBaseDemoAction *action = demoaction->GetAction( i );
		Assert( action );

		KeyValues *item = new KeyValues( "data", "actionname", action->GetActionName() );
		item->SetString( "actiontype", CBaseDemoAction::NameForType( action->GetType() ) );
		switch ( action->GetTimingType() )
		{
		default:
		case ACTION_USES_NEITHER:
			break;
		case ACTION_USES_TICK:
			{
				item->SetString( "actionstart", va( "Tick %i", action->GetStartTick() ) );
			}
			break;
		case ACTION_USES_TIME:
			{
				item->SetString( "actionstart", va( "Time %.3f", action->GetStartTime() ) );
			}
			break;
		}

		m_pActions->AddItem( item , 0, false, false);
	}
}

void CDemoEditorPanel::OnEdit()
{
	if ( m_hCurrentEditor != 0 )
		return;

	int numselected = m_pActions->GetSelectedItemsCount();
	if ( numselected != 1 )
		return;

	int row = m_pActions->GetSelectedItem( 0 );
	if ( row == -1 )
		return;

	CBaseDemoAction *action = demoaction->GetAction( row );

	m_hCurrentEditor = CBaseDemoAction::CreateActionEditor( action->GetType(), this, action, false );
	if ( m_hCurrentEditor != 0 )
	{
		m_hCurrentEditor->SetVisible( true );
		m_hCurrentEditor->SetSize( 400, 300 );
	}
	
	// edit it

//	demoaction->SetDirty( true );

//	PopulateActionList();
}

void CDemoEditorPanel::OnDelete()
{
	int numselected = m_pActions->GetSelectedItemsCount();
	if ( numselected < 1 )
		return;

	int i;
	for ( i = 0; i < numselected; i++ )
	{
		int row = m_pActions->GetSelectedItem(0);
		if ( row == -1 )
			continue;

		CBaseDemoAction *action = demoaction->GetAction( row );
		if ( action )
		{
			// This sets dirty bit
			demoaction->RemoveAction( action );
		}
	}

	OnRefresh();
}

void CDemoEditorPanel::OnSave()
{
	demoaction->SaveToFile();
}

void CDemoEditorPanel::OnRevert()
{
	demoaction->ReloadFromDisk();
	OnRefresh();
}

CBaseDemoAction *CDemoEditorPanel::FindActionByName( char const *name )
{
	int count = demoaction->GetActionCount();
	int i;
	for ( i = 0; i < count; i++ )
	{
		CBaseDemoAction *action = demoaction->GetAction( i );
		Assert( action );
		if ( !Q_strcasecmp( name, action->GetActionName() ) )
			return action;
	}
	return NULL;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CDemoEditorPanel::OnRefresh()
{
	PopulateActionList();
}