#ifndef K3DSDK_ISTATE_RECORDER_H
#define K3DSDK_ISTATE_RECORDER_H

// 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
	\author Tim Shead (tshead@k-3d.com)
*/

#include "istate_change_set.h"
#include "iunknown.h"
#include "signal_system.h"

#include <memory>

namespace k3d
{

/// Encapsulates functionality for recording undo/redo -able state changes
class istate_recorder :
	public virtual iunknown
{
public:
	/// Called by clients to register a change set for recording subsequent state changes
	virtual void start_recording(std::auto_ptr<istate_change_set> ChangeSet) = 0;
	/// Called by clients to stop recording a set of state changes
	virtual std::auto_ptr<istate_change_set> stop_recording() = 0;
	/// Called by clients once a set of changes is complete, to make them a part of the undo/redo stack (the recorder assumes responsibility for the lifetime of the change set)
	virtual void commit_change_set(std::auto_ptr<istate_change_set> ChangeSet, const std::string& Label) = 0;
	/// Returns the current k3dIStateChangeSet (if any - could return NULL) being recorded
	virtual istate_change_set* current_change_set() = 0;

	/// Called to mark the current state as saved
	virtual void mark_saved() = 0;
	/// Returns true iff the recorder contains unsaved changes
	virtual bool unsaved_changes() = 0;

	/// Returns the number of change sets left that can be undone
	virtual unsigned long undo_count() = 0;
	/// Returns the number of undone change set that can be redone
	virtual unsigned long redo_count() = 0;

	/// Returns the label of the state change set that will be undone with the next call to Undo()
	virtual const std::string next_undo_label() = 0;
	/// Returns the label of the state change set that will be redone with the next call to Redo()
	virtual const std::string next_redo_label() = 0;

	/// Called to undo the last change set
	virtual void undo() = 0;
	/// Called to redo the most-recently-undone change set
	virtual void redo() = 0;

	/// Implemented by objects that want to retrieve information about available undo/redo change sets
	class ichange_set_visitor
	{
	public:
		virtual void visit_undo_change_set(const std::string& UndoLabel, const bool Saved) = 0;
		virtual void visit_redo_change_set(const std::string& RedoLabel, const bool Saved) = 0;

	protected:
		ichange_set_visitor() {}
		ichange_set_visitor(const ichange_set_visitor& RHS) {}
		ichange_set_visitor& operator = (const ichange_set_visitor& RHS) { return *this; }
		virtual ~ichange_set_visitor() {}
	};
	/// Enumerates through the entire collection of change sets
	virtual void visit_change_sets(ichange_set_visitor& Visitor) = 0;

	/// Defines a signal for notifying observers that the undo stack has been modified
	typedef SigC::Signal0<void> stack_changed_signal_t;
	virtual stack_changed_signal_t& stack_changed_signal() = 0;

	/// Defines a signal for notifying observers that a save has occurred
	typedef SigC::Signal0<void> mark_saved_signal_t;
	virtual mark_saved_signal_t& mark_saved_signal() = 0;

protected:
	istate_recorder() {}
	istate_recorder(const istate_recorder& RHS) {}
	istate_recorder& operator = (const istate_recorder& RHS) { return *this; }
	virtual ~istate_recorder() {}
};

} // namespace k3d

#endif // K3DSDK_ISTATE_RECORDER_H

