#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "KDChartObjectFactory.h"
#include <KDChartParams.h>
#include <KDChartTable.h>
#include <tqsargument.h>
#include <tqdatetime.h>
#include <KDChartEnums.h>
#include <tqfont.h>
#include <KDChartTextPiece.h>
#include <tqcolor.h>
#include <KDChartWidget.h>
#include <KDChartPropertySet.h>
#include "factories/TQtFactory.h"
#include "factories/TQFontFactory.h"

// PENDING(blackie) Clean up code in this file, so it uses the correct getter methods like getBool.
KDChartObjectFactory::KDChartObjectFactory()
{
    registerClass( TQString::fromLatin1( "KDChartWidget" ) );
    registerClass( TQString::fromLatin1( "KDChartParams" ), new KDChartParams );
    registerClass( TQString::fromLatin1( "KDChartTableData" ) );
    registerClass( TQString::fromLatin1( "KDChartAxisParams" ), new KDChartAxisParams );
    registerClass( TQString::fromLatin1( "KDChartEnums" ), 0, new KDChartEnums );
    registerClass( TQString::fromLatin1( "KDChartTextPiece" ) );
    registerClass( TQString::fromLatin1( "KDChartCustomBox" ), new KDChartCustomBox );
    registerClass( TQString::fromLatin1( "KDChartPropertySet" ), new KDChartPropertySet );
    registerClass( TQString::fromLatin1( "KDFrame" ), TQString(), new KDFrame );

    registerClass( TQString::fromLatin1( "TQt" ), TQString(), new TQtFactory() );
    registerClass( TQString::fromLatin1( "TQFont" ), TQString(), new TQFontFactory );
}

TQObject* KDChartObjectFactory::create( const TQString& className, const TQSArgumentList& args, TQObject* /*context*/ )
{
    if ( className == TQString::fromLatin1( "KDChartWidget" ) )
         return createKDChartWidget( args );

    if ( className == TQString::fromLatin1("KDChartParams") )
        return new KDChartParams();

    else if ( className == TQString::fromLatin1("KDChartTableData") )
        return createKDChartTableData( args );

    else if ( className == TQString::fromLatin1("KDChartAxisParams") )
        return new KDChartAxisParams();


    else if ( className == TQString::fromLatin1( "KDChartTextPiece" ) )
        return createKDChartTextPiece( args );

    else if ( className == TQString::fromLatin1( "KDChartCustomBox" ) )
        return createKDChartCustomBox( args );

    else if ( className == TQString::fromLatin1( "KDChartPropertySet" ) )
        return createKDChartPropertySet( args );

    else
        return 0;
}

TQObject* KDChartObjectFactory::createKDChartWidget( const TQSArgumentList& args )
{
    if ( !checkArgCount( "KDChartWidget", args.count(), 2, 2 ) ) return 0;
    if ( !checkArgsIsTQtClass( args, 1, "KDChartParams", "KDChartWidget" ) ) return 0;
    if ( !checkArgsIsTQtClass( args, 2, "KDChartTableDataBase", "KDChartWidget" ) ) return 0;
    KDChartParams* params = static_cast<KDChartParams*>( args[0].qobject() );
    KDChartTableDataBase* data = static_cast<KDChartTableDataBase*>( args[1].qobject() );

    return new KDChartWidget( params, data );

}

TQObject* KDChartObjectFactory::createKDChartTableData( const TQSArgumentList& args )
{
    if ( args.count() != 2 ) {
        throwError( TQObject::tr( "wrong number of arguments to KDChartTableData" ) );
        return 0;
    }
    TQSArgument arg1 = args[0];
    TQSArgument arg2 = args[1];

    if ( arg1.type() != TQSArgument::Variant || !isNumber(arg1.variant()) ) {
        throwError( TQObject::tr( "wrong type for argument 1 of KDChartTableData" ) );
        return 0;
    }
    if ( arg2.type() != TQSArgument::Variant || !isNumber(arg2.variant() ) ) {
         throwError( TQObject::tr( "wrong type for argument 2 of KDChartTableData" ) );
        return 0;
    }
    return new KDChartTableData( arg1.variant().toUInt(), arg2.variant().toUInt() );
}


TQObject* KDChartObjectFactory::createKDChartTextPiece( const TQSArgumentList& args )
{
    if ( !checkArgCount( "KDChartTextPiece", args.count(), 2, 2 ) ) return 0;
    TQSArgument arg1 = args[0];
    TQSArgument arg2 = args[1];

    TQString str;
    if ( !getString( args, 1, &str, "KDChartTextPiece" ) ) return 0;
    if ( !checkIsTQtVariant( args, 2, TQVariant::Font, TQString::fromLatin1( "TQFont" ), "KDChartTextPiece" ) ) return 0;
    TQFont font = args[1].variant().toFont();

    return new KDChartTextPiece( str, font );
}

TQObject* KDChartObjectFactory::createKDChartCustomBox( const TQSArgumentList& args )
{
    int tmp;

    if ( args.count() == 0 )
        return new KDChartCustomBox();


    if ( args[0].type() == TQSArgument::Variant && isNumber( args[0].variant() ) ) {
        if ( args.count() < 8 ) {
            throwError( TQObject::tr( "Too few arguments to KDChartCustomBox" ) );
            return 0;
        }

        int rotation;
        if ( !getNumber( args, 1, &rotation, "KDChartCustomBox" ) ) return 0;

        if (!checkArgsIsTQtClass( args, 2, "KDChartTextPiece", "KDChartCustomBox" )) return 0;
        KDChartTextPiece* content = static_cast<KDChartTextPiece*>( args[1].qobject() );

        int fontSize;
        if ( !getNumber( args, 3, &fontSize, "KDChartCustomBox" ) ) return 0;


        bool fontScaleGlobal;
        if ( !getBool( args, 4, &fontScaleGlobal, "KDChartCustomBox" ) ) return 0;

        int deltaX;
        if ( !getNumber( args, 5, &deltaX, "KDChartCustomBox" ) ) return 0;

        int deltaY;
        if ( !getNumber( args, 6, &deltaY, "KDChartCustomBox" ) ) return 0;

        int width;
        if ( !getNumber( args, 7, &width, "KDChartCustomBox" ) ) return 0;

        int height;
        if ( !getNumber( args, 8, &height, "KDChartCustomBox" ) ) return 0;

        TQColor color = TQt::black;
        if ( args.count() >= 9 ) {
            if ( !checkIsTQtVariant( args, 9, TQVariant::Color, TQString::fromLatin1( "TQColor" ), "KDChartCustomBox" ) ) return 0;
            color = args[8].variant().toColor();
        }

        TQBrush paper = TQt::NoBrush;
        if ( args.count() >= 10 ) {
            if ( !checkIsTQtVariant( args, 10, TQVariant::Brush, TQString::fromLatin1( "TQBrush" ), "KDChartCustomBox" ) ) return 0;
            paper = args[9].variant().toBrush();
        }

        uint area = KDChartEnums::AreaInnermost;
        if ( args.count() >= 11 ) {
            if ( !getNumber( args, 11, &area, "KDChartCustomBox" ) ) return 0;
        }

        KDChartEnums::PositionFlag position = KDChartEnums::PosTopLeft;
        if ( args.count() >= 12 ) {
            if ( !getNumber( args, 12, &tmp, "KDChartCustomBox" ) ) return 0;
            position = (KDChartEnums::PositionFlag) tmp;
        }

        uint align = TQt::AlignTop + TQt::AlignLeft;
        if ( args.count() >= 13 ) {
            if ( !getNumber( args, 13, &align, "KDChartCustomBox" ) ) return 0;
        }

        uint dataRow = 0;
        if ( args.count() >= 14 ) {
            if ( !getNumber( args, 14, &dataRow, "KDChartCustomBox" ) ) return 0;
        }

        uint dataCol = 0;
        if ( args.count() >= 15 ) {
            if ( !getNumber( args, 15, &dataCol, "KDChartCustomBox" ) ) return 0;
        }

        uint data3rd = 0;
        if ( args.count() >= 16 ) {
            if ( !getNumber( args, 16, &data3rd, "KDChartCustomBox" ) ) return 0;
        }

        uint deltaAlign = KDCHART_AlignAuto;
        if ( args.count() >= 17 ) {
            if ( !getNumber( args, 17, &deltaAlign, "KDChartCustomBox" ) ) return 0;
        }

        bool deltaScaleGlobal = true;
        if ( args.count() >= 18 ) {
            if ( !getBool( args, 18, &deltaScaleGlobal, "KDChartCustomBox" ) ) return 0;
        }

        return new KDChartCustomBox( rotation, *content, fontSize, fontScaleGlobal, deltaX, deltaY,
                                     width, height, color, paper, area, position, align, dataRow,
                                     dataCol, data3rd, deltaAlign, deltaScaleGlobal );
    }

    if (!checkArgsIsTQtClass( args, 1, "KDChartTextPiece", "KDChartCustomBox" )) return 0;
    KDChartTextPiece* content = static_cast<KDChartTextPiece*>( args[0].qobject() );

    if ( args.count() < 2 ) {
        throwError( TQObject::tr( "Too few arguments to KDChartCustomBox" ) );
        return 0;
    }

    int fontSize;
    if ( ! getNumber( args, 2, &fontSize, "KDChartCustomBox" ) ) return 0;

    bool fontScaleGlobal = true;
    if ( args.count() > 2 && !getBool( args, 3, &fontScaleGlobal, "KDChartCustomBox" ) ) return 0;

    if ( args.count() <= 3 )
        return new KDChartCustomBox( *content, fontSize, fontScaleGlobal );

    checkArgCount( "KDChartCustomBox", args.count(), 7, 17 );

    int deltaX;
    if ( !getNumber( args, 4, &deltaX, "KDChartCustomBox" ) ) return 0;

    int deltaY;
    if ( !getNumber( args, 5, &deltaY, "KDChartCustomBox" ) ) return 0;

    int width;
    if ( !getNumber( args, 6, &width, "KDChartCustomBox" ) ) return 0;

    int height;
    if ( !getNumber( args, 7, &height, "KDChartCustomBox" ) ) return 0;


    TQColor color = TQt::black;
    if ( args.count() >= 8 ) {
        if ( !checkIsTQtVariant( args, 8, TQVariant::Color, TQString::fromLatin1( "TQColor" ), "KDChartCustomBox" ) ) return 0;
        color = args[7].variant().toColor();
    }

    TQBrush paper = TQt::NoBrush;
    if ( args.count() >= 9 ) {
        if ( !checkIsTQtVariant( args, 9, TQVariant::Brush, TQString::fromLatin1( "TQBrush" ), "KDChartCustomBox" ) ) return 0;
        paper = args[8].variant().toBrush();
    }

    uint area = KDChartEnums::AreaInnermost;
    if ( args.count() >= 10 ) {
        if ( !getNumber( args, 10, &area, "KDChartCustomBox" ) ) return 0;
    }

    KDChartEnums::PositionFlag position = KDChartEnums::PosTopLeft;
    if ( args.count() >= 11 ) {
        if ( !getNumber( args, 11, &tmp, "KDChartCustomBox" ) ) return 0;
        position = (KDChartEnums::PositionFlag) tmp;
    }

    uint align = TQt::AlignTop + TQt::AlignLeft;
    if ( args.count() >= 12 ) {
        if ( !getNumber( args, 12, &align, "KDChartCustomBox" ) ) return 0;
    }

    uint dataRow = 0;
    if ( args.count() >= 13 ) {
        if ( !getNumber( args, 13, &dataRow, "KDChartCustomBox" ) ) return 0;
    }

    uint dataCol = 0;
    if ( args.count() >= 14 ) {
        if ( !getNumber( args, 14, &dataCol, "KDChartCustomBox" ) ) return 0;
    }

    uint data3rd = 0;
    if ( args.count() >= 15 ) {
        if ( !getNumber( args, 15, &data3rd, "KDChartCustomBox" ) ) return 0;
    }

    uint deltaAlign = KDCHART_AlignAuto;
    if ( args.count() >= 16 ) {
        if ( !getNumber( args, 16, &deltaAlign, "KDChartCustomBox" ) ) return 0;
    }

    bool deltaScaleGlobal = true;
    if ( args.count() >= 17 ) {
        if ( !getBool( args, 17, &deltaScaleGlobal, "KDChartCustomBox" ) ) return 0;
    }


    return new KDChartCustomBox( *content, fontSize, fontScaleGlobal, deltaX, deltaY, width, height, color,
                                 paper, area, position, align, dataRow, dataCol, data3rd, deltaAlign, deltaScaleGlobal );
}

TQObject* KDChartObjectFactory::createKDChartPropertySet(const TQSArgumentList& args )
{
    if ( args.count() == 0 )
        return new KDChartPropertySet();

    TQString name;
    if ( !getString( args, 1, &name, "KDChartPropertySet"  ) ) return 0;

    if ( args.count() == 1 )
        return new KDChartPropertySet( name );

    int i;
    if ( !getNumber( args, 2, &i, "KDChartPropertySet" ) ) return 0;
    if ( args.count() == 2 )
        return new KDChartPropertySet( name, i );

    if ( !checkArgCount( "KDChartPropertySet", args.count(), 33, 33 ) ) return 0;

    int idLineWidth = i;

    int lineWidth;
    if ( !getNumber( args, 3,&lineWidth, "KDChartPropertySet" ) ) return 0;

    int idLineColor;
    if ( !getNumber( args, 4,&idLineColor, "KDChartPropertySet" ) ) return 0;


    if ( !checkIsTQtVariant( args, 5, TQVariant::Color, TQString::fromLatin1( "TQColor" ), "KDChartPropertySet" ) ) return 0;
    TQColor lineColor = args[4].variant().toColor();

    int idLineStyle;
    if ( !getNumber( args, 6,&idLineStyle, "KDChartPropertySet" ) ) return 0;



    if ( !getNumber( args, 7,&i, "KDChartPropertySet" ) ) return 0;
    TQt::PenStyle lineStyle = (TQt::PenStyle) i;

    int idShowMarker;
    if ( !getNumber( args, 8,&idShowMarker, "KDChartPropertySet" ) ) return 0;

    bool showMarker;
    if ( !getBool( args, 9, &showMarker, "KDChartPropertySet" ) ) return 0;

    int idExtraLinesAlign;
    if ( !getNumber( args, 10,&idExtraLinesAlign, "KDChartPropertySet" ) ) return 0;

    uint extraLinesAlign;
    if ( !getNumber( args, 11,&extraLinesAlign, "KDChartPropertySet" ) ) return 0;

    int idExtraLinesInFront;
    if ( !getNumber( args, 12,&idExtraLinesInFront, "KDChartPropertySet" ) ) return 0;

    bool extraLinesInFront;
    if ( !getBool( args, 13, &extraLinesInFront, "KDChartPropertySet" ) ) return 0;

    int idExtraLinesLength;
    if ( !getNumber( args, 14,&idExtraLinesLength, "KDChartPropertySet" ) ) return 0;

    int extraLinesLength;
    if ( !getNumber( args, 15,&extraLinesLength, "KDChartPropertySet" ) ) return 0;

    int idExtraLinesWidth;
    if ( !getNumber( args, 16,&idExtraLinesWidth, "KDChartPropertySet" ) ) return 0;

    int extraLinesWidth;
    if ( !getNumber( args, 17,&extraLinesWidth, "KDChartPropertySet" ) ) return 0;

    int idExtraLinesColor;
    if ( !getNumber( args, 18,&idExtraLinesColor, "KDChartPropertySet" ) ) return 0;

    if ( !checkIsTQtVariant( args, 19, TQVariant::Color, TQString::fromLatin1( "TQColor" ), "KDChartPropertySet" ) ) return 0;
    TQColor extraLinesColor = args[18].variant().toColor();

    int idExtraLinesStyle;
    if ( !getNumber( args, 20,&idExtraLinesStyle, "KDChartPropertySet" ) ) return 0;

    if ( !getNumber( args, 21,&i, "KDChartPropertySet" ) ) return 0;
    TQt::PenStyle extraLinesStyle = (TQt::PenStyle) i;

    int idExtraMarkersAlign;
    if ( !getNumber( args, 22,&idExtraMarkersAlign, "KDChartPropertySet" ) ) return 0;

    uint extraMarkersAlign;
    if ( !getNumber( args, 23,&extraMarkersAlign, "KDChartPropertySet" ) ) return 0;

    int idExtraMarkersSize;
    if ( !getNumber( args, 24,&idExtraMarkersSize, "KDChartPropertySet" ) ) return 0;

    if ( !checkIsTQtVariant( args, 25, TQVariant::Size, TQString::fromLatin1( "TQSize" ), "KDChartPropertySet" ) ) return 0;
    TQSize extraMarkersSize = args[24].variant().toSize();

    int idExtraMarkersColor;
    if ( !getNumber( args, 26,&idExtraMarkersColor, "KDChartPropertySet" ) ) return 0;

    if ( !checkIsTQtVariant( args, 27, TQVariant::Color, TQString::fromLatin1( "TQColor" ), "KDChartPropertySet" ) ) return 0;
    TQColor extraMarkersColor = args[26].variant().toColor();

    int idExtraMarkersStyle;
    if ( !getNumber( args, 28,&idExtraMarkersStyle, "KDChartPropertySet" ) ) return 0;

    int extraMarkersStyle;
    if ( !getNumber( args, 29,&extraMarkersStyle, "KDChartPropertySet" ) ) return 0;

    int idShowBar;
    if ( !getNumber( args, 30,&idShowBar, "KDChartPropertySet" ) ) return 0;

    bool showBar;
    if ( !getBool( args, 31, &showBar, "KDChartPropertySet" ) ) return 0;

    int idBarColor;
    if ( !getNumber( args, 32,&idBarColor, "KDChartPropertySet" ) ) return 0;

    if ( !checkIsTQtVariant( args, 33, TQVariant::Color, TQString::fromLatin1( "TQColor" ), "KDChartPropertySet" ) ) return 0;
    TQColor barColor = args[32].variant().toColor();

    KDChartPropertySet* set = new KDChartPropertySet;
    set->setName( name );
    set->setLineWidth( idLineWidth, lineWidth );
    set->setLineColor( idLineColor, lineColor );
    set->setLineStyle( idLineStyle, lineStyle );
    set->setShowMarker( idShowMarker, showMarker );
    set->setExtraLinesAlign( idExtraLinesAlign, extraLinesAlign );
    set->setExtraLinesInFront( idExtraLinesInFront, extraLinesInFront );
    set->setExtraLinesLength( idExtraLinesLength, extraLinesLength );
    set->setExtraLinesWidth( idExtraLinesWidth, extraLinesWidth );
    set->setExtraLinesColor( idExtraLinesColor, extraLinesColor );
    set->setExtraLinesStyle( idExtraLinesStyle, extraLinesStyle );
    set->setExtraMarkersAlign( idExtraMarkersAlign, extraMarkersAlign );
    set->setExtraMarkersSize( idExtraMarkersSize, extraMarkersSize );
    set->setExtraMarkersColor( idExtraMarkersColor, extraMarkersColor );
    set->setExtraMarkersStyle( idExtraMarkersStyle, extraMarkersStyle );
    set->setShowBar( idShowMarker, showBar );
    set->setBarColor( idBarColor, barColor );
    return set;
}


bool KDChartObjectFactory::isNumber( const TQVariant& v )
{
    return ( v.type() == TQVariant::Int || v.type() == TQVariant::UInt || v.type() == TQVariant::Double );
}

    // PENDING(blackie) rework order of parameters so it matches the other methods
bool KDChartObjectFactory::checkArgCount( const TQString& className, int count, int min, int max )
{
    if ( count < min ) {
        throwError( TQObject::tr( "Too few arguments when creating %1 object." ).arg( className ) );
        return false;
    }
    if ( count > max ) {
        throwError( TQObject::tr( "Too many arguments when creating %1 object." ).arg( className ) );
        return false;
    }
    return true;
}


bool KDChartObjectFactory::checkArgsIsTQtClass( const TQSArgumentList& args, int index, const char* expected, const char* constructing )
{
    const TQSArgument& arg = args[index-1];
    if ( arg.type() != TQSArgument::TQObjectPtr || !arg.qobject()->inherits( expected ) ) {
        throwError( TQObject::tr( "Invalid type for argument no %1 to %2, must be a %3" ).arg(index).arg(constructing).arg(expected) );
        return false;
    }
    return true;
}


bool KDChartObjectFactory::getString( const TQSArgumentList& args, int index, TQString* str, const char* constructing  )
{
    const TQSArgument& arg = args[index-1];
    if ( arg.type() != TQSArgument::Variant || arg.variant().type() != TQVariant::String ) {
        throwError( TQObject::tr( "Invalid type for argument %1 to %2, must be a string" ).arg(index).arg(constructing) );
        return false;
    }
    else {
        *str = arg.variant().toString();
        return true;
    }
}

bool KDChartObjectFactory::getNumber( const TQSArgumentList& args, int index, double* number, const char* constructing )
{
    const TQSArgument& arg = args[index-1];
    if ( arg.type() != TQSArgument::Variant || !isNumber(arg.variant()) ) {
        throwError( TQObject::tr( "Invalid type for argument %1 to %2, must be a number" ).arg(index).arg( constructing ) );
        return false;
    }
    else {
        *number = arg.variant().toDouble();
        return true;
    }
}

bool KDChartObjectFactory::getNumber( const TQSArgumentList& args, int index, int* number, const char* constructing )
{
    double tmp;
    bool ok = getNumber( args, index, &tmp, constructing );
    *number = static_cast<int>( tmp );
    return ok;
}

bool KDChartObjectFactory::getNumber( const TQSArgumentList& args, int index, uint* number, const char* constructing )
{
    double tmp;
    bool ok = getNumber( args, index, &tmp, constructing );
    *number = static_cast<uint>( tmp );
    return ok;
}



bool KDChartObjectFactory::getBool( const TQSArgumentList& args, int index, bool* b, const char* constructing )
{
    const TQSArgument& arg = args[index-1];
    if ( arg.type() != TQSArgument::Variant || arg.variant().type() != TQVariant::Bool ) {
        throwError( TQObject::tr( "Invalid type for argument %1 to %2, must be a boolean" ).arg(index).arg( constructing ) );
        return false;
    }
    else {
        *b = arg.variant().toBool();
        return true;
    }
}

bool KDChartObjectFactory::checkIsTQtVariant( const TQSArgumentList& args, int index, TQVariant::Type expected, const TQString& variantName, const char* constructing )
{
    const TQSArgument& arg = args[index-1];
    if ( arg.type() != TQSArgument::Variant || arg.variant().type() != expected ) {
        throwError( TQObject::tr( "Invalid type for argument %1 to %2, must be a %3").arg(index).arg(constructing).arg(variantName) );
        return false;
    }
    else
        return true;
}


