/****************************************************************************
** $Id: quickpixmapobject.cpp  beta1   edited Dec 12 16:27 $
**
** Copyright (C) 2001-2002 Trolltech AS.  All rights reserved.
**
** This file is part of the Qt Script for Applications framework (QSA).
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** Licensees holding a valid QSA Beta Evaluation Version license may use
** this file in accordance with the QSA Beta Evaluation Version License
** Agreement provided with the Software.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
**   information about QSA Commercial License Agreements.
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
*****************************************************************************/

#include "quickpixmapobject.h"
#include "quickbytearrayobject.h"
#include "quickinterpreter.h"
#include <qsfunction.h>
#include <qimage.h>
#include <qpixmap.h>
#include <qbuffer.h>
#include <assert.h>
#include <quickcoordobjects.h>
#include <quickcolorobject.h>
#include <qimage.h>
#include <qfileinfo.h>

class PixmapShared : public QSShared {
public:
    PixmapShared( const QPixmap &p ) : pixmap( p ) { }
    QPixmap pixmap;
};

enum { Width, Height, Rect, Size, Depth };

QSPixmapClass::QSPixmapClass( QSClass *b )
  : QSClass( b )
{
    addMember( "width", QSMember( QSMember::Custom, Width,
				  AttributeNonWritable ) );
    addMember( "height", QSMember( QSMember::Custom, Height,
				   AttributeNonWritable ) );
    addMember( "rect", QSMember( QSMember::Custom, Rect,
				 AttributeNonWritable ) );
    addMember( "size", QSMember( QSMember::Custom, Size,
				 AttributeNonWritable ) );
    addMember( "depth", QSMember( QSMember::Custom, Depth,
				 AttributeNonWritable ) );
    addMember( "isNull", QSMember( &isNull ) );
    addMember( "fill", QSMember( &fill ) );
    addMember( "resize", QSMember( &resize ) );
    addMember( "load", QSMember( &load ) );
    addMember( "save", QSMember( &save ) );
}

QPixmap *QSPixmapClass::pixmap( const QSObject *obj ) const
{
    assert( obj->objectType() == this );
    return &((PixmapShared*)obj->shVal())->pixmap;
}

QSObject QSPixmapClass::fetchValue( const QSObject *obj,
				    const QSMember &mem ) const
{
    if ( mem.type() == QSMember::Custom ) {
	switch ( mem.index() ) {
	case Width:
	    return QSNumber( pixmap( obj )->width() );
	case Height:
	    return QSNumber( pixmap( obj )->height() );
	case Rect:
	    return QuickInterpreter::self()->rectClass()->construct( pixmap( obj )->rect() );
	case Size:
	    return QuickInterpreter::self()->sizeClass()->construct( pixmap( obj )->size() );
	case Depth:
	    return QSNumber( pixmap( obj )->depth() );
	default:
	    qWarning( "QSPixmapClass::fetchValue: unhandled case" );
	    return QSUndefined();
	}
    } else {
	return QSClass::fetchValue( obj, mem );
    }
}

QString QSPixmapClass::debugString( const QSObject * ) const
{
    return "\"...\":Pixmap"; // ###
}

QSObject QSPixmapClass::construct( const QSList &args ) const
{
    if ( args.size() > 0 ) {
	QSObject v( args[ 0 ] );
	if ( v.isA( "Pixmap" ) ) {
	    return v;
	} else if ( v.isA( "String" ) ) {
	    QPixmap pm( v.toString() );
	    return construct( pm );
	}
    }
    return construct( QPixmap() );
}

QSObject QSPixmapClass::construct( const QPixmap &p ) const
{
    return QSObject( this, new PixmapShared( p ) );
}

QSObject QSPixmapClass::isNull( QSObject *obj, const QSList & )
{
    assert( obj->isA( "Pixmap" ) );
    QSPixmapClass *pac = (QSPixmapClass*)obj->objectType();

    QSObject result;
    QPixmap *pix = pac->pixmap( obj );
    return QSBoolean( pix->isNull() );
}

extern void qsa_throw_error( const QString &message );

QSObject QSPixmapClass::fill( QSObject *obj, const QSList &args )
{
    assert( obj->isA( "Pixmap" ) );
    QSPixmapClass *pac = (QSPixmapClass*)obj->objectType();

    if ( args.size() != 1 ) {
	qsa_throw_error( QString( "Pixmap.fill() called with %1 arguments. 1 arguments expected." ).
			 arg( args.size() ) );
	return QSUndefined();
    }

    QSObject a0 = args[0];
    if ( !a0.isA( "Color" ) ) {
	qsa_throw_error( QString( "Pixmap.fill() called with an argument of type %1. "
				  "Type Color is expeced" ).
			 arg( a0.typeName() ) );
	return QSUndefined();
    }

    QPixmap *pix = pac->pixmap( obj );
    pix->fill( *( (QSColorClass*)a0.objectType() )->color( &a0 ) );
    return QSUndefined();
}

QSObject QSPixmapClass::resize( QSObject *obj, const QSList &args )
{
    assert( obj->isA( "Pixmap" ) );
    QSPixmapClass *pac = (QSPixmapClass*)obj->objectType();

    if ( args.size() < 1 || args.size() > 2 ) {
	qsa_throw_error( QString( "Pixmap.resize() called with %1 arguments. 1 or 2 arguments expected." ).
			 arg( args.size() ) );
	return QSUndefined();
    }

    QPixmap *pix = pac->pixmap( obj );
    if ( args.size() == 1 ) {
	QSObject a0 = args[0];
	if ( !a0.isA( "Size" ) ) {
	    qsa_throw_error( QString( "Pixmap.resize() called with an argument of type %1. "
				  "Type Size is expeced" ).
			     arg( a0.typeName() ) );
	    return QSUndefined();
	}
	pix->resize( *( (QSSizeClass*)a0.objectType() )->size( &a0 ) );
    } else {
	if ( !args[0].isA( "Number" ) || !args[1].isA( "Number" ) ) {
	    qsa_throw_error( QString( "Pixmap.resize() called with arguments of type %1 and %2. "
				  "Type Number and Number is expeced" ).
			     arg( args[0].typeName() ).arg( args[1].typeName() ) );
	    return QSUndefined();
	}
	pix->resize( args[0].toInteger(), args[1].toInteger() );
    }

    return QSUndefined();
}

QSObject QSPixmapClass::load( QSObject *obj, const QSList &args )
{
    assert( obj->isA( "Pixmap" ) );
    QSPixmapClass *pac = (QSPixmapClass*)obj->objectType();

    if ( args.size() != 1 ) {
	qsa_throw_error( QString( "Pixmap.load() called with %1 arguments. 1 argument expected." ).
			 arg( args.size() ) );
	return QSUndefined();
    }

    QPixmap *pix = pac->pixmap( obj );
    if ( !args[0].isA( "String" ) ) {
	qsa_throw_error( QString( "Pixmap.load() called with an argument of type %1. "
				  "Type String is expeced" ).
			 arg( args[0].typeName() ) );
	return QSUndefined();
    }

    pix->load( args[0].toString() );

    return QSUndefined();
}

QSObject QSPixmapClass::save( QSObject *obj, const QSList &args )
{
    assert( obj->isA( "Pixmap" ) );
    QSPixmapClass *pac = (QSPixmapClass*)obj->objectType();

    if ( args.size() < 1 || args.size() > 2 ) {
	qsa_throw_error( QString( "Pixmap.save() called with %1 arguments. 1 or 2 argument expected." ).
			 arg( args.size() ) );
	return QSUndefined();
    }

    QPixmap *pix = pac->pixmap( obj );
    if ( !args[0].isA( "String" ) ) {
	qsa_throw_error( QString( "Pixmap.save() called with an argument of type %1. "
				  "Type String is expeced" ).
			 arg( args[0].typeName() ) );
	return QSUndefined();
    }

    QString format = QFileInfo( args[0].toString() ).extension().upper();
    QStrList l = QImageIO::outputFormats();
    if ( l.find( format ) == -1 )
	format = "PNG";

    if ( args.size() == 2 ) {
	if ( !args[1].isA( "String" ) ) {
	    qsa_throw_error( QString( "Pixmap.save() called with an argument of type %1. "
				      "as second argument. Type String is expeced" ).
			 arg( args[1].typeName() ) );
	    return QSUndefined();
	}
	format = args[1].toString();
    }

    pix->save( args[0].toString(), format );

    return QSUndefined();
}
