/**
 * \file PreviewImage.C
 * This file is part of LyX, the document processor.
 * Licence details can be found in the file COPYING.
 *
 * \author Angus Leeming
 *
 * Full author contact details are available in file CREDITS.
 */

#include <config.h>

#include "PreviewImage.h"
#include "GraphicsImage.h"
#include "GraphicsLoader.h"
#include "PreviewLoader.h"

#include "support/lyxlib.h"

#include <boost/bind.hpp>

namespace support = lyx::support;

using std::string;


namespace lyx {
namespace graphics {

class PreviewImage::Impl : public boost::signals::trackable {
public:
	///
	Impl(PreviewImage & p, PreviewLoader & l,
	     string const & s, string const & f, double af);
	///
	~Impl();
	///
	Image const * image();
	///
	void statusChanged();

	///
	PreviewImage const & parent_;
	///
	PreviewLoader & ploader_;
	///
	Loader iloader_;
	///
	string const snippet_;
	///
	double const ascent_frac_;
};


PreviewImage::PreviewImage(PreviewLoader & l,
			   string const & s,
			   string const & f,
			   double af)
	: pimpl_(new Impl(*this, l, s, f, af))
{}


PreviewImage::~PreviewImage()
{}


string const & PreviewImage::snippet() const
{
	return pimpl_->snippet_;
}


int PreviewImage::ascent() const
{
	Image const * const image = pimpl_->iloader_.image();
	if (!image)
		return 0;

	return int(pimpl_->ascent_frac_ * double(image->getHeight()));
}


int PreviewImage::descent() const
{
	Image const * const image = pimpl_->iloader_.image();
	if (!image)
		return 0;

	// Avoids rounding errors.
	return image->getHeight() - ascent();
}


int PreviewImage::width() const
{
	Image const * const image = pimpl_->iloader_.image();
	return image ? image->getWidth() : 0;
}


Image const * PreviewImage::image() const
{
	return pimpl_->image();
}


PreviewImage::Impl::Impl(PreviewImage & p, PreviewLoader & l,
			 string const & s,
			 string const & bf,
			 double af)
	: parent_(p), ploader_(l), iloader_(bf),
	  snippet_(s), ascent_frac_(af)
{
	iloader_.connect(boost::bind(&Impl::statusChanged, this));
}


PreviewImage::Impl::~Impl()
{
	support::unlink(iloader_.filename());
}


Image const * PreviewImage::Impl::image()
{
	if (iloader_.status() == WaitingToLoad)
		iloader_.startLoading();

	return iloader_.image();
}


void PreviewImage::Impl::statusChanged()
{
	switch (iloader_.status()) {
	case WaitingToLoad:
	case Loading:
	case Converting:
	case Loaded:
	case ScalingEtc:
		break;

	case ErrorNoFile:
	case ErrorConverting:
	case ErrorLoading:
	case ErrorGeneratingPixmap:
	case ErrorUnknown:
		//lyx::unlink(iloader_.filename());
		ploader_.remove(snippet_);
		break;

	case Ready:
		support::unlink(iloader_.filename());
		break;
	}
	ploader_.emitSignal(parent_);
}

} // namespace graphics
} // namespace lyx
