/*
 *  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 "jsbinding.h"
#include "jsobjectproxy.h"
#include "jsconsolewidget.h"
#include "image_imp.h"
#include "textstream_imp.h"
#include "kjsembedpart_imp.h"

#include "factory.h"

//
// KPart Implementation
//
namespace KJSEmbed {

//
// Factory
//

KJS::Interpreter *JSFactory::createInterpreter()
{
    KJS::Object global( new KJS::ObjectImp() );
    KJS::Interpreter *js = new KJS::Interpreter( global );
    return js;
}

QObject *JSFactory::create( QString cname, QObject *parent, const char *name ) 
{
//    kdDebug() << "KJSEmbedPart::create() name " << name << " class " << cname << endl;

    // Actions
    if ( cname == "KAction" )
	return new KAction( parent, name );
    else if ( cname == "KToggleAction" )
	return new KToggleAction( parent, name );

    // Widgets
    QWidget *pw=0;
    if ( parent && parent->isWidgetType() ) {
	pw = static_cast<QWidget *>( parent );
    }

    QWidgetFactory wf;
    QWidget *w = wf.createWidget( cname, pw, name );
    if ( w )
	return w;

    // Bindings
    if ( cname == "Image" )
	return new Bindings::Image( parent, name );

    return 0;
}

QWidget *JSFactory::loadUI( const QString &uiFile, QObject *connector, QWidget *parent, const char *name )
{
    return QWidgetFactory::create( uiFile, connector, parent, name );
}

KJS::Object JSFactory::bind( KJS::Interpreter *js, QObject *obj )
{
    JSObjectProxy *proxy = new JSObjectProxy( js, obj );
    KJS::Object o(proxy);
    proxy->addBindings( js->globalExec(), o );
    return o;
}

KJS::Object JSFactory::addObject( KJS::Interpreter *js, QObject *obj, KJS::Object &parent, const char *name )
{
    KJS::Object jsobj;
    if ( obj && js ) {
	jsobj = JSFactory::bind( js, obj );
	parent.put( js->globalExec(), name ? name : obj->name(), jsobj );
    }

    return jsobj;
}

void JSFactory::addStdBindings( KJSEmbedPart *part, KJS::ExecState *state, KJS::Object &parent )
{
    addBuiltIn( part, state, parent );
    addFactory( part, state, parent );
    addIO( part, state, parent );
    addSystem( part, state, parent );
    addWidgets( part, state, parent );

    parent.put( state, "self", parent );
}

void JSFactory::addBuiltIn( KJSEmbedPart *part, KJS::ExecState *state, KJS::Object &parent )
{
    parent.put( state ,"Image", KJS::Object( createPartImp(part, Bindings::KJSEmbedPartImp::ConstructImage) ) );
    parent.put( state ,"TextStream", KJS::Object( createPartImp( part, Bindings::KJSEmbedPartImp::ConstructTextStream ) ) );
    parent.put( state ,"dump", KJS::Object( createPartImp( part, Bindings::KJSEmbedPartImp::MethodDumpObject ) ) );
}

void JSFactory::addFactory( KJSEmbedPart *part, KJS::ExecState *state, KJS::Object &parent )
{
    KJS::Object object( new KJS::ObjectImp() );
    parent.put( state, "Factory", object );

    object.put( state ,"create", KJS::Object( createPartImp( part, Bindings::KJSEmbedPartImp::MethodCreate ) ) );
    object.put( state ,"loadui", KJS::Object( createPartImp( part, Bindings::KJSEmbedPartImp::MethodLoadUI ) ) );
    object.put( state ,"load", KJS::Object( createPartImp( part, Bindings::KJSEmbedPartImp::MethodLoadScript ) ) );
}

void JSFactory::addIO( KJSEmbedPart *part, KJS::ExecState *state, KJS::Object &parent )
{
    parent.put( state ,"print", KJS::Object( createPartImp( part, Bindings::KJSEmbedPartImp::MethodPrint ) ) );
    parent.put( state ,"println", KJS::Object( createPartImp( part, Bindings::KJSEmbedPartImp::MethodPrintLn ) ) );
    parent.put( state ,"warn", KJS::Object( createPartImp( part, Bindings::KJSEmbedPartImp::MethodWarn ) ) );
    parent.put( state ,"readLine", KJS::Object( createPartImp( part, Bindings::KJSEmbedPartImp::MethodReadLine ) ) );
}

void JSFactory::addSystem( KJSEmbedPart *part, KJS::ExecState *state, KJS::Object &parent )
{
    KJS::Object stdio( new KJS::ObjectImp() );
    parent.put( state, "System", stdio );

    KJS::Interpreter *js = part->interpreter();
    addObject( js, new Bindings::TextStream( part, "stdin", new QTextStream(stdin, IO_ReadOnly) ), stdio );
    addObject( js, new Bindings::TextStream( part, "stdout", new QTextStream(stdout, IO_WriteOnly) ), stdio );
    addObject( js, new Bindings::TextStream( part, "stderr", new QTextStream(stderr, IO_WriteOnly) ), stdio );
    stdio.put( state ,"readFile", KJS::Object( createPartImp( part, Bindings::KJSEmbedPartImp::MethodReadFile ) ) );
}

void JSFactory::addWidgets( KJSEmbedPart *part, KJS::ExecState *state, KJS::Object &parent )
{
    // QWidget Constructors
    const char *classes[] = {

	"QPushButton", "QToolButton", "QCheckBox", "QRadioButton",
	"QGroupBox", "QButtonGroup", "QIconView", "QTable",
	"QListBox", "QListView", "QLineEdit", "QSpinBox",
	"QMultiLineEdit", "QLabel", "TextLabel", "PixmapLabel",
	"QLayoutWidget", "QTabWidget", "QComboBox",
	"QWidget", "QDialog", "QWizard", "QLCDNumber",
	"QProgressBar", "QTextView", "QTextBrowser",
	"QDial", "QSlider", "QFrame", "Line", "QTextEdit",
	"QDateEdit", "QTimeEdit", "QDateTimeEdit", "QScrollBar",
	"QPopupMenu", "QWidgetStack", "QMainWindow",
	"QDataTable", "QDataBrowser", "QDataView",
	"QVBox", "QHBox", "QGrid",

	"KActiveLabel", "KCharSelect", "KColorButton", "KColorCombo",
	"KComboBox", "KCModule", "KDateWidget", "KDatePicker", "KDialog",
	"KDualColorButton", "KEditListBox", "KFontCombo", "KGradientSelector",
	"KHistoryCombo", "KHSSelector", "KLed", "KListBox", "KListView",
	"KLineEdit", "KPasswordEdit", "KProgress", "KPushButton",
	"KRestrictedLine", "KIconButton", "KIntSpinBox", "KRuler",
	"KSqueezedTextLabel", "KTextBrowser", "KTextEdit",
	"KURLLabel", "KURLRequester",
	"KIntNumInput", "KDoubleNumInput", "KDoubleSpinBox",

	0
    };

    int i=0;
    do {
	Bindings::KJSEmbedPartImp *cons = createPartImp( part, Bindings::KJSEmbedPartImp::ConstructQObject, classes[i] );
	parent.put( state, cons->parameter(), KJS::Object( cons ) );

	i++;
    } while ( classes[i] );
}

Bindings::KJSEmbedPartImp *JSFactory::createPartImp( KJSEmbedPart *part, int id, const QString &param )
{
    return new Bindings::KJSEmbedPartImp( part, id, param );
}

}; // namespace KJSEmbed

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

