#include "GeckoThumbnailer.h"

#include "rendako.h"
#include "GeckoPrivate.h"

#define MOZILLA_INTERNAL_API
#include <nsICanvasRenderingContextInternal.h>
#undef MOZILLA_INTERNAL_API
#include <nsIDOMCanvasRenderingContext2D.h>
#include <nsIComponentManager.h>
#include <nsComponentManagerUtils.h>
#include <nsIDocShellTreeItem.h>
#include <nsIWebNavigation.h>
#include <nsEmbedCID.h>
#include <nsIDOMWindowInternal.h>
#include <gtk/gtk.h>


GeckoThumbnailer::GeckoThumbnailer()
{
	mOwner        = NULL;
	mProgress     = nsnull;
	mParentWidget = NULL;
	mWidget       = NULL;
	mURI	      = NULL;
	mCreating     = PR_FALSE;
}

GeckoThumbnailer::~GeckoThumbnailer()
{
	if (mParentWidget)
	{
		gtk_widget_destroy (mParentWidget);
	}

	if (mURI)
	{
		g_free (mURI);
		mURI = NULL;
	}
}

NS_IMETHODIMP
GeckoThumbnailer::Init (RdThumbnailer *owner)
{
	nsresult rv;

	mOwner = owner;

	mParentWidget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	gtk_window_set_default_size (GTK_WINDOW(mParentWidget), RD_IMAGE_WIDTH, -1);
	gtk_widget_realize (mParentWidget);

	mWidget = gtk_fixed_new ();
	gtk_container_add (GTK_CONTAINER (mParentWidget), mWidget);
	gtk_widget_show (mWidget);

	mWebBrowser = do_CreateInstance (NS_WEBBROWSER_CONTRACTID, &rv);
	NS_ENSURE_SUCCESS (rv, rv);

	nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface (mWebBrowser,  &rv);
	NS_ENSURE_SUCCESS (rv, rv);

	rv = item->SetItemType (nsIDocShellTreeItem::typeContentWrapper);
	NS_ENSURE_SUCCESS (rv, rv);

  	mBaseWindow = do_QueryInterface(mWebBrowser, &rv);
	NS_ENSURE_SUCCESS (rv, rv);

	rv = mBaseWindow->InitWindow(mWidget, nsnull, 0, 0, RD_IMAGE_WIDTH, 1);
	NS_ENSURE_SUCCESS (rv, rv);

	rv = mBaseWindow->Create ();
	NS_ENSURE_SUCCESS (rv, rv);

	rv = mBaseWindow->SetVisibility (PR_TRUE);
	NS_ENSURE_SUCCESS (rv, rv);

	mProgress = new GeckoProgress;
	mProgress->Init (this);
	mProgressGuard = NS_STATIC_CAST(nsIWebProgressListener *, mProgress);

	nsCOMPtr<nsISupportsWeakReference> supportsWeak;
	supportsWeak = do_QueryInterface (mProgressGuard);
	nsCOMPtr<nsIWeakReference> weakRef;

	supportsWeak->GetWeakReference (getter_AddRefs(weakRef));
	mWebBrowser->AddWebBrowserListener (weakRef, nsIWebProgressListener::GetIID());
}

NS_IMETHODIMP
GeckoThumbnailer::Destroy ()
{
	nsCOMPtr<nsISupportsWeakReference> supportsWeak;
	supportsWeak = do_QueryInterface (mProgressGuard);
	nsCOMPtr<nsIWeakReference> weakRef;
	supportsWeak->GetWeakReference (getter_AddRefs(weakRef));
	mWebBrowser->RemoveWebBrowserListener (weakRef, nsIWebProgressListener::GetIID());

	weakRef        = nsnull;
	supportsWeak   = nsnull;
	mProgressGuard = nsnull;
	mProgress      = nsnull;

	mBaseWindow->Destroy ();
	mBaseWindow    = nsnull;
	mWebBrowser    = nsnull;
}

NS_IMETHODIMP
GeckoThumbnailer::AppendQueue (const char *uri)
{
	nsresult rv;

	mCreating = PR_TRUE;
	if (mURI)
		g_free (mURI);

	mURI = g_strdup (uri);

	nsCOMPtr<nsIWebNavigation> navigation;
	navigation = do_QueryInterface (mWebBrowser);

	GeckoPrivate::LoadURI (navigation, uri);

	return NS_OK;
}

NS_IMETHODIMP
GeckoThumbnailer::CreateThumbnail ()
{
	nsresult rv;

	nsCOMPtr<nsIDOMWindow> domWindow;
	rv = mWebBrowser->GetContentDOMWindow (getter_AddRefs(domWindow));
	if (NS_FAILED(rv)) 
	{
		mCreating = PR_FALSE;
		return rv;
	}

	nsCOMPtr<nsIDOMWindowInternal> internalWindow;
	internalWindow = do_QueryInterface (domWindow);

	nsCOMPtr<nsICanvasRenderingContextInternal> context;
	context = do_CreateInstance ("@mozilla.org/content/canvas-rendering-context;1?id=2d", &rv);
	if (NS_FAILED(rv)) 
	{
		mCreating = PR_FALSE;
		return rv;
	}

	PRInt32 wWidth, wHeight;
	PRInt32 sMaxX, sMaxY;
	internalWindow->GetInnerWidth (&wWidth);
	internalWindow->GetInnerHeight (&wHeight);
	internalWindow->GetScrollMaxX (&sMaxX);
	internalWindow->GetScrollMaxY (&sMaxY);

	PRInt32 w, h;
	w = wWidth + sMaxX;
	h = wHeight + sMaxY;

	context->SetDimensions (w, h);

	// Call SetCanvasElement to make a nsICSSParser in nsICanvasRenderingContextInternal.
	context->SetCanvasElement (nsnull);

	nsCOMPtr<nsIDOMCanvasRenderingContext2D> domCanvas = do_QueryInterface (context, &rv);
	if (NS_FAILED(rv)) 
	{
		mCreating = PR_FALSE;
		return rv;
	}

	domCanvas->Scale (1.0, 1.0);
	domCanvas->Save ();

	rv = GeckoPrivate::DrawWindow (domCanvas, domWindow, w, h);
	if (NS_FAILED(rv)) 
	{
		mCreating = PR_FALSE;
		return rv;
	}

	cairo_surface_t *cs;
	cs = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
	rv = context->RenderToSurface (cs);
	if (NS_FAILED(rv)) 
	{
		mCreating = PR_FALSE;
		return rv;
	}

	domCanvas->Restore ();

	g_signal_emit_by_name (mOwner, "ready", cs, mURI);
	cairo_surface_destroy (cs);

	mCreating = PR_FALSE;

	return NS_OK;
}

PRBool
GeckoThumbnailer::IsCreating ()
{
	return mCreating;
}

NS_IMETHODIMP
GeckoThumbnailer::GetWebBrowser (nsIWebBrowser * *aWebBrowser)
{
	*aWebBrowser = mWebBrowser;
	NS_IF_ADDREF (*aWebBrowser);
	return NS_OK;
}

NS_IMETHODIMP
GeckoThumbnailer::SetWebBrowser (nsIWebBrowser * aWebBrowser)
{
	mWebBrowser = aWebBrowser;
	return NS_OK;
}
