/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2003-2004 Hiroyuki Ikezoe
 *
 *  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, 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.
 */

#include "kz-mozprogresslistener.h"
#include "gobject-utils.h"
#include "kz-downloader-group.h"
#include "kz-mozdownloader.h"

#include <nsIFileURL.h>
#include <nsILocalFile.h>
#include <nsAString.h>
#include <nsString.h>

KzMozProgressListener::KzMozProgressListener()
{
	mDownloader = nsnull;
	mPersist    = nsnull;
	NS_INIT_ISUPPORTS();
}


KzMozProgressListener::~KzMozProgressListener()
{
}

NS_IMPL_ISUPPORTS3(KzMozProgressListener,
		   nsIDownload,
		   nsIWebProgressListener,
		   nsISupportsWeakReference)

NS_IMETHODIMP
KzMozProgressListener::OnStateChange(nsIWebProgress *aWebProgress,
				     nsIRequest     *aRequest,
				     PRUint32        aStateFlags,
				     nsresult        aStatus)
{
	if (aStateFlags & nsIWebProgressListener::STATE_STOP)
	{
		if (mPersist)
		{
			PRUint32 aCurrentState;
			mPersist->GetCurrentState(&aCurrentState);
			if (aCurrentState == nsIWebBrowserPersist::PERSIST_STATE_FINISHED)
			{
				g_signal_emit_by_name(G_OBJECT(mDownloader), "completed");
				// Is it memory leak, isn't it?
				mPersist->SetProgressListener(nsnull);
				g_object_unref(mDownloader);
				mDownloader = nsnull;
			}
		}
		else if (NS_SUCCEEDED(aStatus))
		{
			g_signal_emit_by_name(G_OBJECT(mDownloader), "completed");
			g_object_unref(mDownloader);
			mDownloader = nsnull;
		}
	}

	return NS_OK;
}

NS_IMETHODIMP
KzMozProgressListener::OnProgressChange(nsIWebProgress *aWebProgress,
					nsIRequest     *aRequest,
					PRInt32         aCurSelfProgress,
					PRInt32         aMaxSelfProgress,
					PRInt32         aCurTotalProgress,
					PRInt32         aMaxTotalProgress)
{

	mPercentComplete = (PRInt32)(((float)aCurTotalProgress / (float)aMaxTotalProgress) * 100.0 + 0.5);

	mTotalProgress = aMaxTotalProgress;
	mCurrentProgress = aCurTotalProgress;
	g_signal_emit_by_name(G_OBJECT(mDownloader), "io_in");
	return NS_OK;
}

NS_IMETHODIMP
KzMozProgressListener::OnLocationChange(nsIWebProgress *aWebProgress,
					nsIRequest     *aRequest,
					nsIURI         *aLocation)
{
	return NS_OK;
}

NS_IMETHODIMP
KzMozProgressListener::OnStatusChange(nsIWebProgress  *aWebProgress,
				      nsIRequest      *aRequest,
				      nsresult         aStatus,
				      const PRUnichar *aMessage)
{
	return NS_OK;
}

NS_IMETHODIMP
KzMozProgressListener::OnSecurityChange(nsIWebProgress *aWebProgress,
					nsIRequest     *aRequest,
					PRUint32         aState)
{
	return NS_OK;
}

NS_IMETHODIMP
KzMozProgressListener::Init(nsIURI *aSource,
#if MOZILLA_SNAPSHOT >14
			    nsIURI *aTarget,
#else			    
			    nsILocalFile *aTarget,
#endif
			    const PRUnichar *aDisplayName,
			    nsIMIMEInfo *aMIMEInfo,
			    PRInt64 startTime,
			    nsIWebBrowserPersist *aPersist)
{
	mTotalProgress = 0;
	mCurrentProgress = 0;
	mPercentComplete = 0;

	if (aPersist)
	{
		mPersist = aPersist;
		mPersist->SetProgressListener(this);
        }

	nsAutoString leafName;
#if MOZILLA_SNAPSHOT > 14
	nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(aTarget);
	if (fileUrl)
	{
        	nsCOMPtr<nsIFile> file;
        	fileUrl->GetFile(getter_AddRefs(file));
		file->GetLeafName(leafName);
	}
#else
	aTarget->GetLeafName(leafName);
#endif
	KzDownloaderGroup *dlgrp = kz_downloader_group_get_instance();
#if 0
	mDownloader = kz_downloader_group_add_moz_downloader(dlgrp,
							     this,
							     NS_ConvertUCS2toUTF8(leafName).get());
#else
	mDownloader = kz_moz_downloader_new(this, NS_ConvertUCS2toUTF8(leafName).get());
	kz_downloader_group_add_downloader(dlgrp, KZ_DOWNLOADER(mDownloader));
#endif
	g_object_unref(dlgrp);
	return NS_OK;
}

NS_IMETHODIMP
KzMozProgressListener::GetSource(nsIURI * *aSource)
{
	return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
#if MOZILLA_SNAPSHOT >14
KzMozProgressListener::GetTarget(nsIURI * *aTarget)
#else
KzMozProgressListener::GetTarget(nsILocalFile * *aTarget)
#endif
{
	return NS_ERROR_NOT_IMPLEMENTED;
}

#if MOZILLA_SNAPSHOT >14
NS_IMETHODIMP
KzMozProgressListener::GetTargetFile(nsILocalFile * *aTarget)
{
	return NS_ERROR_NOT_IMPLEMENTED;
}
#endif

NS_IMETHODIMP
KzMozProgressListener::GetPersist(nsIWebBrowserPersist * *aPersist)
{
        NS_IF_ADDREF(*aPersist = mPersist);
	return NS_OK;
}

NS_IMETHODIMP
KzMozProgressListener::GetPercentComplete(PRInt32 *aPercentComplete)
{	
	NS_ENSURE_ARG_POINTER(aPercentComplete);
	*aPercentComplete = mPercentComplete;

	return NS_OK;
}

NS_IMETHODIMP
KzMozProgressListener::GetDisplayName(PRUnichar * *aDisplayName)
{
	return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
KzMozProgressListener::SetDisplayName(const PRUnichar * aDisplayName)
{
	return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
KzMozProgressListener::GetStartTime(PRInt64 *aStartTime)
{
	return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
KzMozProgressListener::GetMIMEInfo(nsIMIMEInfo * *aMIMEInfo)
{
	return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
KzMozProgressListener::GetListener(nsIWebProgressListener * *aListener)
{
	NS_ENSURE_ARG_POINTER(aListener);
	NS_IF_ADDREF(*aListener = (nsIWebProgressListener *)this);
	return NS_OK;
}

NS_IMETHODIMP
KzMozProgressListener::SetListener(nsIWebProgressListener * aListener)
{
	return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
KzMozProgressListener::GetObserver(nsIObserver * *aObserver)
{
	return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
KzMozProgressListener::SetObserver(nsIObserver * aObserver)
{
        mObserver = aObserver;
	return NS_OK;
}

nsresult
KzMozProgressListener::Cancel ()
{

        if (mObserver)
        {
                this->OnStateChange(nsnull, nsnull,
				    nsIWebProgressListener::STATE_STOP, 0);		
                mObserver->Observe(nsnull, "oncancel", nsnull);
        }

        if (mPersist)
        {
                return mPersist->CancelSave ();
        }
	
	return NS_ERROR_FAILURE;
}

