#include "SkImageView.h"
#include "SkAnimator.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkImageDecoder.h"
#include "SkMatrix.h"
#include "SkSystemEventTypes.h"
#include "SkTime.h"

SkImageView::SkImageView()
{
	fMatrix		= nil;
	fScaleType	= kMatrix_ScaleType;

	fData.fAnim	= nil;		// handles initializing the other union values
	fDataIsAnim	= true;
	
	fUriIsValid	= false;	// an empty string is not valid
}

SkImageView::~SkImageView()
{
	if (fMatrix)
		sk_free(fMatrix);
		
	this->freeData();
}

void SkImageView::getUri(SkString* uri) const
{
	if (uri)
		*uri = fUri;
}

void SkImageView::setUri(const char uri[])
{
	if (!fUri.equals(uri))
	{
		fUri.set(uri);
		this->onUriChange();
	}
}

void SkImageView::setUri(const SkString& uri)
{
	if (fUri != uri)
	{
		fUri = uri;
		this->onUriChange();
	}
}

void SkImageView::setScaleType(ScaleType st)
{
	SkASSERT((unsigned)st <= kFitEnd_ScaleType);

	if ((ScaleType)fScaleType != st)
	{
		fScaleType = SkToU8(st);
		if (fUriIsValid)
			this->inval(nil);
	}
}

bool SkImageView::getImageMatrix(SkMatrix* matrix) const
{
	if (fMatrix)
	{
		SkASSERT(!fMatrix->isIdentity());
		if (matrix)
			*matrix = *fMatrix;
		return true;
	}
	else
	{
		if (matrix)
			matrix->reset();
		return false;
	}
}

void SkImageView::setImageMatrix(const SkMatrix* matrix)
{
	bool changed = false;

	if (matrix && !matrix->isIdentity())
	{
		if (fMatrix == nil)
			fMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix));
		*fMatrix = *matrix;
		changed = true;
	}
	else	// set us to identity
	{
		if (fMatrix)
		{
			SkASSERT(!fMatrix->isIdentity());
			sk_free(fMatrix);
			fMatrix = nil;
			changed = true;
		}
	}

	// only redraw if we changed our matrix and we're not in scaleToFit mode
	if (changed && this->getScaleType() == kMatrix_ScaleType && fUriIsValid)
		this->inval(nil);
}

///////////////////////////////////////////////////////////////////////////////////////////////

bool SkImageView::onEvent(const SkEvent& evt)
{
	if (evt.isType(SK_EventType_Inval))
	{
		if (fUriIsValid)
			this->inval(nil);
		return true;
	}
	return this->INHERITED::onEvent(evt);
}

static inline SkMatrix::ScaleToFit scaleTypeToScaleToFit(SkImageView::ScaleType st)
{
	SkASSERT(st != SkImageView::kMatrix_ScaleType);
	SkASSERT((unsigned)st <= SkImageView::kFitEnd_ScaleType);

	SkASSERT(SkImageView::kFitXY_ScaleType - 1 == SkMatrix::kFill_ScaleToFit);
	SkASSERT(SkImageView::kFitStart_ScaleType - 1 == SkMatrix::kStart_ScaleToFit);
	SkASSERT(SkImageView::kFitCenter_ScaleType - 1 == SkMatrix::kCenter_ScaleToFit);
	SkASSERT(SkImageView::kFitEnd_ScaleType - 1 == SkMatrix::kEnd_ScaleToFit);
	
	return (SkMatrix::ScaleToFit)(st - 1);
}

void SkImageView::onDraw(SkCanvas* canvas)
{
	SkRect	src;
	if (!this->getDataBounds(&src))
	{
		SkDEBUGCODE(canvas->drawColor(SK_ColorRED);)
		return;		// nothing to draw
	}
		
	SkAutoCanvasRestore	restore(canvas, true);
	SkMatrix			matrix;
	
	if (this->getScaleType() == kMatrix_ScaleType)
		(void)this->getImageMatrix(&matrix);
	else
	{
		SkRect	dst;		
		dst.set(0, 0, this->width(), this->height());
		matrix.setRectToRect(src, dst, scaleTypeToScaleToFit(this->getScaleType()));
	}
	canvas->concat(matrix);

	SkPaint	paint;
	
	paint.setAntiAlias(true);

	if (fDataIsAnim)
	{
		SkMSec	now = SkTime::GetMSecs();
		
		SkAnimator::DifferenceType diff = fData.fAnim->draw(canvas, &paint, now);
		
SkDEBUGF(("SkImageView : now = %X[%12.3f], diff = %d\n", now, now/1000., diff));

		if (diff == SkAnimator::kDifferent)
			this->inval(nil);
		else if (diff == SkAnimator::kPartiallyDifferent)
		{
			SkRect	bounds;
			fData.fAnim->getInvalBounds(&bounds);
			matrix.mapRect(&bounds);	// get the bounds into view coordinates
			this->inval(&bounds);
		}
	}
	else
		canvas->drawBitmap(*fData.fBitmap, 0, 0, &paint);
}

void SkImageView::onInflate(const SkDOM& dom, const SkDOMNode* node)
{
	this->INHERITED::onInflate(dom, node);
	
	const char* src = dom.findAttr(node, "src");
	if (src)
		this->setUri(src);

	int	index = dom.findList(node, "scaleType", "matrix,fitXY,fitStart,fitCenter,fitEnd");
	if (index >= 0)
		this->setScaleType((ScaleType)index);
		
	// need inflate syntax/reader for matrix
}

/////////////////////////////////////////////////////////////////////////////////////

void SkImageView::onUriChange()
{
	if (this->freeData())
		this->inval(nil);
	fUriIsValid = true;		// give ensureUriIsLoaded() a shot at the new uri
}

bool SkImageView::freeData()
{
	if (fData.fAnim)	// test is valid for all union values
	{
		if (fDataIsAnim)
			delete fData.fAnim;
		else
			delete fData.fBitmap;

		fData.fAnim = nil;	// valid for all union values
		return true;
	}
	return false;
}

bool SkImageView::getDataBounds(SkRect* bounds)
{
	SkASSERT(bounds);

	if (this->ensureUriIsLoaded())
	{
		SkScalar width, height;

		if (fDataIsAnim)
		{			
			if (SkScalarIsNaN(width = fData.fAnim->getScalar("dimensions", "x")) ||
				SkScalarIsNaN(height = fData.fAnim->getScalar("dimensions", "y")))
			{
				// cons up fake bounds
				width = this->width();
				height = this->height();
			}
		}
		else
		{
			width = SkIntToScalar(fData.fBitmap->width());
			height = SkIntToScalar(fData.fBitmap->height());
		}
		bounds->set(0, 0, width, height);
		return true;
	}
	return false;
}

bool SkImageView::ensureUriIsLoaded()
{
	if (fData.fAnim)	// test is valid for all union values
	{
		SkASSERT(fUriIsValid);
		return true;
	}
	if (!fUriIsValid)
		return false;

	// try to load the url
	if (fUri.endsWith(".xml"))	// assume it is screenplay
	{
		SkAnimator* anim = new SkAnimator;
		
		if (!anim->decodeURI(fUri.c_str()))
		{
			delete anim;
			fUriIsValid = false;
			return false;
		}
		anim->setHostEventSink(this);

		fData.fAnim = anim;
		fDataIsAnim = true;
	}
	else	// assume it is an image format
	{
    #if 0
		SkBitmap* bitmap = new SkBitmap;

		if (!SkImageDecoder::DecodeURL(fUri.c_str(), bitmap))
		{
			delete bitmap;
			fUriIsValid = false;
			return false;
		}
		fData.fBitmap = bitmap;
		fDataIsAnim = false;
    #else
        return false;
    #endif
	}
	return true;
}

