// K-3D
// Copyright (c) 1995-2004, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/** \file
		\brief Implements the black_box_recorder class, which records user actions in realtime for troubleshooting purposes
		\author Tim Shead (tshead@k-3d.com)
*/

#include "black_box_recorder.h"
#include "button.h"

#include <k3dsdk/application.h>
#include <k3dsdk/ideletable.h>
#include <k3dsdk/iscript_engine.h>
#include <k3dsdk/classes.h>
#include <k3dsdk/plugins.h>
#include <k3dsdk/result.h>

#include <sdpgtk/sdpgtkfileselector.h>
#include <sdpgtk/sdpgtkevents.h>

namespace k3d
{

/////////////////////////////////////////////////////////////////////////////
// black_box_recorder

black_box_recorder::black_box_recorder(k3d::icommand_node& Parent, const boost::filesystem::path& LogFile) :
	base(&Parent, "black_box_recorder", new k3d::options_window_geometry_store()),
	m_log_file(LogFile),
	m_log_stream(LogFile)
{
	// We want to be notified when the application is closed
	k3d::application().close_signal().connect(SigC::slot(*this, &black_box_recorder::OnClose));

	// Create the UI ...
	return_if_fail(LoadGTKMLTemplate("black_box_recorder.gtkml"));

	if(get_button("close"))
		get_button("close")->signal_activate().connect(SigC::slot(*this, &black_box_recorder::OnClose));

	// Display the output filepath in our titlebar ...
	RootWindow().SetTitle(LogFile.native_file_string());

	// Try opening the file ...
	return_if_fail(m_log_stream.good());

	// Connect to the scripting engine ...
	m_script_engine = dynamic_cast<k3d::iscript_engine*>(k3d::create_application_plugin(k3d::classes::JavaScriptEngine()));
	return_if_fail(m_script_engine);

	// Give the engine a chance to "bless" this script so it can be identified later ...
	std::string buffer;
	m_script_engine->bless_script(buffer);
	m_log_stream << buffer << std::endl;
	m_log_stream.flush();

	// We want to observe command events as they happen ...
	k3d::application().command_signal().connect(SigC::slot(*this, &black_box_recorder::on_command));

	Show();
}

black_box_recorder::~black_box_recorder()
{
	delete dynamic_cast<k3d::ideletable*>(m_script_engine);
}

void black_box_recorder::on_command(k3d::icommand_node* CommandNode, k3d::icommand_node::command_t::type_t Type, std::string Name, std::string Arguments)
{
	// We only want user interface commands ... !
	if(Type != k3d::icommand_node::command_t::USER_INTERFACE)
		return;

	// Sanity checks ...
	return_if_fail(CommandNode);
	return_if_fail(!Name.empty());

	std::string buffer;
	m_script_engine->convert_command(*CommandNode, Name, Arguments, buffer);

	m_log_stream << buffer << std::endl;
	m_log_stream.flush();
}

} // namespace k3d

