/////////////////////////////////////////////////////////////////////////////
// Name:        No names yet.
// Purpose:     Contrib. demo
// Author:      Aleksandras Gluchovas
// Modified by:
// Created:     2000/02/08
// RCS-ID:      $Id: scriptproc.cpp,v 1.2 2001/02/27 01:38:46 aleksandras Exp $
// Copyright:   (c) Aleksandras Gluchovas
// Licence:   	GPL (version 2.0 or later)
/////////////////////////////////////////////////////////////////////////////

#ifdef __GNUG__
    #pragma implementation "markersvc.cpp"
    #pragma interface "markersvc.h"
#endif

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#ifndef WX_PRECOMP
    #include "wx/wx.h"
#endif

#include "scriptproc.h"
#include "myutils.h"

/***** Implementation for class ScriptProcessor *****/

BasicScriptProcessorTemplate::BasicScriptProcessorTemplate( ScriptProcessor* pProc )

	: mpProc( pProc )
{}

wxString BasicScriptProcessorTemplate::Handle_subscript( char* at, ScriptTemplate& templ )
{
	// format: "@subscript[subscriptName]"

	++at; // skip '['

	char* start = at;
	while( *at && *at != ']' && *at != ',' ) ++at;

	wxString result;

	wxString name;
	ConcatString( name, start, size_t(at - start) );

	ScriptTemplate* pTempl = mpProc->FindSubscriptByName( name );

	if ( pTempl == NULL )

		return "[@subscript:ERROR: Requested subscript " + name + " not found!]";

	pTempl->Reset();
	pTempl->SetParentTemplate( &templ );

	if ( *at != ']' )
	{
		++at;

		result = Handle_assign_var( at, *pTempl );
	}

	wxString body = pTempl->SubstitueVariables();

	if ( result.Length() ) return result + body;

	return body;
}

wxString BasicScriptProcessorTemplate::Handle_assign_var( char* at, ScriptTemplate& templ )
{
	// format: "@assign_var[var="value"]"

	if ( *at == '[' )

		++at;

	for(;;)
	{
		char* start = at;
		while( *at && *at != ']' && *at != '=' ) ++at;
		wxString varName = wxString( start, 0, size_t(at - start) );

		if ( *at != '=' ) return "[assign_var:ERROR: '=' missing!]";

		++at; // skip '=';

		bool isConstant = *at == '\"';

		if ( isConstant ) ++at;

		start = at;

		while( ( *at && *at != ']' && *at != ',' ) || *at == '\"' ) 
			
			++at;

		if ( isConstant ) --at; // do not include trailing "\"";

		wxString rhs = wxString( start, 0, size_t(at - start) );

		if ( isConstant ) ++at;

		if ( isConstant )

			templ.SetVar( varName, MakeTmpString( rhs ) );
		else
		{
			char* value = templ.FindValue( rhs );

			if ( value != NULL )

				templ.SetVar( varName, MakeTmpString( value ) );
			else
				return "ERROR: cannot @assign_var value of which is not present: " + rhs;
		}

		if ( *at == ']' ) break;
					 else ++at; // skip ','
	}

	return "";
}

wxString BasicScriptProcessorTemplate::Handle_inc_var( char* at, ScriptTemplate& templ )
{
	// format: "@inc_var[var]"

	++at; // skip '['

	char* start = at;

	while( *at && *at != ']' ) ++at;

	wxString varName = wxString( start, 0, size_t(at - start) );

	ScriptTemplate* pTempl = templ.FindTemplateForValue( varName );

	if ( !pTempl ) pTempl = &templ;

	char* value = templ.FindValue( varName );

	int intValue = 0;

	if ( value != NULL ) intValue = atoi( value );

	++intValue;

	pTempl->SetVar( varName, MakeTmpString( IntToStr(intValue) ) );

	return "";
}

/***** Implementation for class ScriptProcessor *****/

ScriptProcessor::ScriptProcessor()

	: mSubscriptHash( wxKEY_STRING ),
	  mpTopTempl( NULL )
{
}

ScriptProcessor::~ScriptProcessor()
{
	CleanUp();
}

void ScriptProcessor::SetProcessorTemplate( ScriptTemplate* pTopTempl )
{
	mpTopTempl = pTopTempl;
}

ScriptTemplate* ScriptProcessor::GetProcessorTemplate()
{
	if ( !mpTopTempl )

		mpTopTempl = new BasicScriptProcessorTemplate( this );

	return mpTopTempl;
}

bool ScriptProcessor::LoadAndProcessConfig( const wxString& fname )
{
	return ProcessConfigContent( LoadFileContent( fname ) );
}

bool ScriptProcessor::ProcessConfigContent( const wxString& text )
{
	InMemoryRecordSet rset( text );
	rset.MoveFirst();

	while( !rset.IsEof() )
	{
		Record& rec = rset.GetRecord();

		const wxString& name = rec.GetName();

		if ( IsScriptSection( name ) )
		{
			ScriptTemplate* pSub = new ScriptTemplate();
			pSub->SetName( rec[ "name" ] );
			pSub->SetScript( rec[ "content" ] );

			pSub->SetParentTemplate( GetProcessorTemplate() );

			mSubscripts.Add( pSub );
			mSubscriptHash.Put( pSub->GetName(), (wxObject*)pSub );
		}
		else
		{
			if ( !ProcessSection( rec ) )

				return FALSE;
		}

		rset.MoveNext();
	}

	return TRUE;
}

bool ScriptProcessor::IsScriptSection( const wxString& name )
{
	return name == "script";
}

bool ScriptProcessor::ProcessSection( Record& rec )
{
	// nothing by default
	return TRUE;
}

ScriptTemplate* ScriptProcessor::FindSubscriptByName( const wxString& name )
{
	return (ScriptTemplate*)mSubscriptHash.Get( name );
}

void ScriptProcessor::CleanUp()
{
	WX_CLEAR_ARRAY( mSubscripts );
	mSubscriptHash.Clear();
	if ( mpTopTempl ) 
	{
		delete mpTopTempl;
		mpTopTempl = NULL;
	}
}