/* -*- 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 <nsIChannel.h>
#include <nsIHttpChannel.h>
#include <nsILocalFile.h>
#define MOZILLA_STRICT_API
#include <nsEmbedString.h>
#undef MOZILLA_STRICT_API

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


KzMozProgressListener::~KzMozProgressListener()
{
}

#ifdef HAVE_NSITRANSFER_H
NS_IMPL_ISUPPORTS2(KzMozProgressListener,
    		   nsIWebProgressListener,
		   nsITransfer)
#else
NS_IMPL_ISUPPORTS2(KzMozProgressListener,
		   nsIDownload,
		   nsIWebProgressListener)
#endif

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(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(mDownloader, "completed");
			g_object_unref(mDownloader);
			mDownloader = nsnull;
		}
	}

	return NS_OK;
}

#ifdef HAVE_NSIWEBPROGRESSLISTENER2_H
NS_IMETHODIMP
KzMozProgressListener::OnProgressChange (nsIWebProgress *aWebProgress,
			                 nsIRequest *aRequest,
				       	 PRInt32 aCurSelfProgress,
				       	 PRInt32 aMaxSelfProgress,
				       	 PRInt32 aCurTotalProgress,
				       	 PRInt32 aMaxTotalProgress)
{
	return OnProgressChange64 (aWebProgress, aRequest,
				   aCurSelfProgress, aMaxSelfProgress,
				   aCurTotalProgress, aMaxTotalProgress);
}

NS_IMETHODIMP
KzMozProgressListener::OnProgressChange64(nsIWebProgress *aWebProgress,
				          nsIRequest *aRequest,
					  PRInt64 aCurSelfProgress,
					  PRInt64 aMaxSelfProgress,
					  PRInt64 aCurTotalProgress,
					  PRInt64 aMaxTotalProgress)
#else 
NS_IMETHODIMP
KzMozProgressListener::OnProgressChange(nsIWebProgress *aWebProgress,
					nsIRequest     *aRequest,
					PRInt32         aCurSelfProgress,
					PRInt32         aMaxSelfProgress,
					PRInt32         aCurTotalProgress,
					PRInt32         aMaxTotalProgress)
#endif
{

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

	mTotalProgress = aMaxTotalProgress;
	mCurrentProgress = aCurTotalProgress;
	g_signal_emit_by_name(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,
			    nsIURI *aTarget,
#if HAVE_NSIWEBPROGRESSLISTENER2_H
			    const nsAString &aDisplayName,
			    nsIMIMEInfo *aMIMEInfo,
			    PRTime aStartTime,
		            nsILocalFile *aTempFile,
		            nsICancelable *aCancelable)
#else
			    const PRUnichar *aDisplayName,
			    nsIMIMEInfo *aMIMEInfo,
			    PRInt64 startTime,
			    nsIWebBrowserPersist *aPersist)
#endif
{
	mTotalProgress = 0;
	mCurrentProgress = 0;
	mPercentComplete = 0;

#ifndef HAVE_NSIWEBPROGRESSLISTENER2_H
	if (aPersist)
	{
		mPersist = aPersist;
		mPersist->SetProgressListener(this);
        }
#endif
	nsEmbedString leafName;

	nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(aTarget);
	if (fileUrl)
	{
        	nsCOMPtr<nsIFile> file;
        	fileUrl->GetFile(getter_AddRefs(file));
		file->GetLeafName(leafName);
	}
	KzDownloaderGroup *dlgrp = kz_downloader_group_get_instance();
	nsEmbedCString cLeafName;
	NS_UTF16ToCString(leafName, NS_CSTRING_ENCODING_UTF8, cLeafName);
	mDownloader = kz_moz_downloader_new(this, cLeafName.get());
	kz_downloader_group_add_downloader(dlgrp, KZ_DOWNLOADER(mDownloader));

	g_object_unref(dlgrp);
	return NS_OK;
}

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

#ifndef HAVE_NSITRANSFER_H
NS_IMETHODIMP
KzMozProgressListener::GetTarget(nsIURI * *aTarget)
{
	return NS_ERROR_NOT_IMPLEMENTED;
}
#endif

NS_IMETHODIMP
KzMozProgressListener::GetTargetFile(nsILocalFile * *aTarget)
{
	return NS_ERROR_NOT_IMPLEMENTED;
}

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

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

	return NS_OK;
}

#ifndef HAVE_NSITRANSFER_H
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;
}
#endif

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

#ifndef HAVE_NSIWEBPROGRESSLISTENER2_H
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;
}
#endif

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;
}

