#ifndef _IPartCountProgress_h_
#define _IPartCountProgress_h_

#include "buildspec.h"
#include <boost/shared_ptr.hpp>

namespace GST
{
namespace Utils
{

class IPartCountProgress;
typedef boost::shared_ptr<IPartCountProgress> PCProgressPtr;

/**
 * Interface that is used to notify for progress
 *
 * @see SimplePercentageProgress for a base implementation
 */
class IPartCountProgress
{
public:
	/**
	 * Called at the begin of a task to tell about number of parts (=steps
	 * required to finish the task)
	 */
	virtual void SetNumberOfParts(int all_parts) = 0;

	/**
	 * Called at the begin to extent the number of steps. Use this with care and
	 * only if your taks has not been started to do the real work.
	 *
	 * If you like to finer granulate some progress please use subdivide!
	 */
	virtual void AppendNumberOfParts(int new_Parts) = 0;

	/**
	 * Called whenever a parts (=a step finished). To be able to manage
	 * "weighted" tasks (to express some tasks are more worksome than others),
	 * you can close more parts once by passing parts different to 1. Of course
	 * this requires to specify more parts at the begin.
	 *
	 * @note Take care to call OnePartFinished() the amount you specified before
	 * (within SetNumberOfParts + AppendNumberOfParts)
	 *
	 * @return the parts remaining
	 */
	virtual int OnePartFinished(int parts = 1) = 0;

	/**
	 * Called to finish all remaining parts once (Equal to \code
	 * OnePartFinished(getPartsRemaining()) \endcode )
	 */
	virtual int Done() = 0;

	/**
	 * New interface: Returns a new Progress to express subparts. This allows to
	 * finer granulate sub work to complete a part. (Example: Upload data
	 * requires 2 parts. Part1: Read data. Part2: Upload data. Part1 can be
	 * subdivided into two parts 1: file read, 2: parsing).
	 *
	 * @params subparts Express how many parts your subprogress needs (in the
	 * example Part1: Read data will be subdivided by 2: read, parsing)
	 *
	 * @params thisWeightParts Use this when a progress is weighted.
	 * (This happens when AppendNumberOfParts() is passing more than one part
	 * for a task and OnePartFinished() is closing more than one part once.) In
	 * this case pass the parts weight that you use in OnePartFinished() in
	 * order to let the sub progress being calculated correct for this weighted
	 * task.
	 */
	virtual PCProgressPtr subdivide(int subparts = 1, int thisWeightParts = 1)
		= 0;

	/**
	 * @returns Remaining parts that are expected calls to OnePartFinished until
	 * task is finished.
	 */
	virtual int getPartsRemaining() const = 0;

	/**
	 * @returns The over all parts passed to SetNumberOfParts() +
	 * AppendNumberOfParts()
	 */
	virtual int getPartCount() const = 0;
};

//------------------------------------------------------------------------------

/**
 * Base implementation that computes the percentage progress from the
 * IPartCountProgress calls. Derive this in you progress handler and update your
 * view	from it. getPercent get the hint about the remaining work.
 */
class GST_API_EXPORT SimplePercentageProgress : public IPartCountProgress
{
public:
	SimplePercentageProgress(int parts = 0);

	virtual void SetNumberOfParts(int all_parts);
	virtual void AppendNumberOfParts(int new_Parts);
	virtual int OnePartFinished(int parts = 1);
	virtual int Done();

	virtual PCProgressPtr subdivide(int subparts = 1, int thisWeightParts = 1);
	virtual int getPartsRemaining() const;
	virtual int getPartCount() const;

	/**
	 * @returns the progress in percent (values: 0 .. 100)
	 */
	int getPercent() const;

	/**
	 * @returns true if the current instance is the top level
	 * IPartCountProgress. Returns false if this instance ws generated trough
	 * subdivide
	 */
	bool isRoot() const;

protected:
	int m_allParts;
	int m_partsDone;
	int m_thisWeightParts;
	boost::shared_ptr<SimplePercentageProgress> m_subProgress;
	SimplePercentageProgress *m_parent;

	virtual boost::shared_ptr<SimplePercentageProgress> create(int parts
															   = 0) const;
};

} // namespace Utils
} // namespace GST

#endif // _IPartCountProgress_h_
