/*
 *  Copyright (C) 2001-2003, Richard J. Moore <rich@kde.org>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 *  Boston, MA 02111-1307, USA.
 */

#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <qobject.h>
#include <qdialog.h>
#include <qfile.h>
#include <qtextstream.h>
#include <qwidget.h>
#include <qwidgetfactory.h>

#include <kaction.h>
#include <kdebug.h>

#include <kjs/interpreter.h>
#include <kjs/ustring.h>
#include <kjs/types.h>

#include "factory.h"
#include "jsbinding.h"
#include "jsobjectproxy.h"
#include "jsconsolewidget.h"
#include "image_imp.h"
#include "textstream_imp.h"

#include "kjsembedpart.h"
#include "kjsembedpart.moc"
#include "kjsembedpart_imp.h"

namespace KJSEmbed {

//
// KPart
//

KJSEmbedPart::KJSEmbedPart( QObject *parent, const char *name )
    : KParts::ReadOnlyPart( parent, name ? name : "kjsembed_part" ),
	      KJSEmbed::XMLActionRunner(),
	      widgetparent(0), widgetname(name ? name : "kjsembed_part"),
	      jsConsole(0), deletejs(true)
{
    js = JSFactory::createInterpreter();
    global = js->globalObject();
    publishStdBindings();

    xmlclient = new KJSEmbed::XMLActionClient( this );
    xmlclient->setActionCollection( actionCollection() );
    xmlclient->setRunner( this );
}

KJSEmbedPart::KJSEmbedPart( QWidget *wparent, const char *wname, QObject *parent, const char *name )
    : KParts::ReadOnlyPart( parent, name ? name : (wname?wname:"jsembed_part") ),
	      widgetparent(wparent), widgetname(wname),
	      jsConsole(0), deletejs(true)
{
    js = JSFactory::createInterpreter();
    global = js->globalObject();
    publishStdBindings();

    xmlclient = new KJSEmbed::XMLActionClient( this );
    xmlclient->setActionCollection( actionCollection() );
    xmlclient->setRunner( this );
}

KJSEmbedPart::KJSEmbedPart( KJS::Interpreter *jsi, QWidget *wparent, const char *wname,
			  QObject *parent, const char *name )
    : KParts::ReadOnlyPart( parent, name ? name : (wname?wname:"jsembed_part") ),
	      widgetparent(wparent), widgetname(wname),
	      js(jsi), jsConsole(0), deletejs(false)
{
    if ( !js ) {
	js = JSFactory::createInterpreter();
	deletejs = true;
    }
    global = js->globalObject();
    publishStdBindings();

    xmlclient = new KJSEmbed::XMLActionClient( this );
    xmlclient->setActionCollection( actionCollection() );
    xmlclient->setRunner( this );
}

KJSEmbedPart::~KJSEmbedPart()
{
    if ( deletejs )
	delete js;
}

JSConsoleWidget *KJSEmbedPart::view()
{
    if ( !jsConsole ) {
	QCString name = widgetname ? widgetname : QCString("jsembed_console");
	jsConsole = new JSConsoleWidget( js, widgetparent, name );
	setWidget( jsConsole );
    }
    return jsConsole;
}

bool KJSEmbedPart::openURL( const KURL &url )
{
    if ( url.protocol() == "javascript" ) {
//	kdDebug() << "KJSEmbedPart: openURL '" << url.url() << "' is javascript" << endl;

	QString cmd = url.url();
	QString js( "javascript:" );
	cmd = cmd.replace( 0, js.length(), QString("") );

//	kdDebug() << "KJSEmbedPart: JS command is '" << cmd << "'" << endl;
	return jsConsole->execute( cmd );
    }
    return false;
}

bool KJSEmbedPart::openURL( const QString &u )
{
    return openURL( KURL(u) );
}

bool KJSEmbedPart::executeScript( const QString &name )
{
//    kdDebug() << "KJSEmbedPart::executeScript(): Script name is '" << name << "'" << endl;

    QString script = loadScript( name );
    KJS::Completion res = js->evaluate( script, js->globalObject() );
    if ( (res.complType() == KJS::Normal) || (res.complType() == KJS::ReturnValue) )
	return true;

    return false;
}

bool KJSEmbedPart::execute( const QString &script )
{
    KJS::Completion res = js->evaluate( script, global );
    if ( (res.complType() == KJS::Normal) || (res.complType() == KJS::ReturnValue) )
	return true;

    return false;
}

bool KJSEmbedPart::loadActionSet( const QString &file )
{
    return xmlclient->load( file );
}

QString KJSEmbedPart::loadScript( const QString &src )
{
    QString script;

    if ( src == "-" ) {
	QTextStream ts( stdin, IO_ReadOnly );
	script = ts.read();
    }
    else {
	QFile file( src );
	if ( file.open( IO_ReadOnly ) ) {
	    script = QString( file.readAll() );
	}
	else {
	    kdWarning() << "Could not open file '" << src << "', "
			<< strerror( errno ) << endl;
	    return QString::null;
	}
    }

    if ( script.startsWith( "#!" ) ) {
	int pos = script.find( "\n" );
	if ( pos > 0 )
	    script = script.mid( pos );
    }

    return script;
}

bool KJSEmbedPart::run( KJSEmbed::XMLActionClient *client, const KJSEmbed::XMLActionScript &script )
{
    if ( script.type == "js" )
	return executeScript( script.src );
    else
	return XMLActionRunner::run( client, script );
}

KJS::Object KJSEmbedPart::publish( QObject *obj, const char *name )
{
    return JSFactory::addObject( js, obj, global, name );
}

void KJSEmbedPart::publishStdBindings()
{
    JSFactory::addStdBindings( this, js->globalExec(), global );
}


}; // namespace KJSEmbed

// Local Variables:
// c-basic-offset: 4
// End:
