#include "defs.h"

#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/classes.h>
#include <intuition/icclass.h>
#include <intuition/gadgetclass.h>
#include <intuition/imageclass.h>

#include <classact.h>

#include <proto/dos.h>
#include <proto/intuition.h>
#include <clib/alib_protos.h>

#include "boopsi_misc.h"
#include "af_button.h"



#define     THISCLASS_ID            NULL
#define     SUPERCLASS_ID           BUTTONGCLASS
#define     SUPERCLASS_PTR          NULL


/*
 * Private class types
 */

struct InstanceData
{
    int Ticks;
};


/*
 * Private functions
 */


static ULONG SAVEDS dispatcher( REG(a0) Class *cl, REG(a2) Object *o, REG(a1) Msg msg );
static ULONG goactive_method( Class *cl, Object *o, struct gpInput *msg );
static ULONG handleinput_method( Class *cl, Object *o, struct gpInput *msg );


/*
 * Private data
 */

static Class *class_base;



/*
 * Public functions
 */

Class
*AFBUTTON_GetClass( VOID )
{
    return class_base;
}


VOID
_INIT_7_AFBUTTON_MakeClass( VOID )
{
    if( class_base = MakeClass( THISCLASS_ID, SUPERCLASS_ID, SUPERCLASS_PTR, sizeof(struct InstanceData), 0L ) )
        class_base->cl_Dispatcher.h_Entry = (ULONG (*)()) dispatcher;

    return;
}


VOID
_EXIT_7_AFBUTTON_FreeClass( VOID )
{
    if( class_base )
        FreeClass( class_base );
}




static ULONG SAVEDS
dispatcher( REG(a0) Class *cl, REG(a2) Object *o, REG(a1) Msg msg )
{
    switch(msg->MethodID)
    {
        /* overridden methods */
        case GM_GOACTIVE:       return( goactive_method(    cl, o, (struct gpInput *) msg ) );
        case GM_HANDLEINPUT:    return( handleinput_method( cl, o, (struct gpInput *) msg ) );

        /* pass any other methods to superclass for handling */
        default:                return( DoSuperMethodA( cl, o, msg ) );
  }
}



static ULONG
goactive_method( Class *cl, Object *obj, struct gpInput *msg )
{
    struct InstanceData *data     = INST_DATA( cl, obj );
    data->Ticks = 4;
    NotifyAttrChanges( obj, msg->gpi_GInfo, OPUF_INTERIM, GA_ID, ((struct Gadget *)obj)->GadgetID, TAG_DONE );
    return GMR_MEACTIVE;
}

static ULONG
handleinput_method( Class *cl, Object *obj, struct gpInput *msg )
{
    UWORD                selected = 0;
    ULONG                retval   = GMR_MEACTIVE;
    struct InstanceData *data     = INST_DATA( cl, obj );

    /* This also works with classic (non-boopsi) images. */
    if( PointInImage( ( msg->gpi_Mouse.X << 16 ) + ( msg->gpi_Mouse.Y ), ((struct Gadget *) obj)->GadgetRender ) )
    {
        /* We are hit */
        selected = GFLG_SELECTED;
    }

    if( msg->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE && msg->gpi_IEvent->ie_Code == SELECTUP )
    {
        /* Gadgetup, time to go */
        retval = GMR_NOREUSE;
        /* Unselect the gadget on our way out... */
        selected = 0;
    }

    if( msg->gpi_IEvent->ie_Class == IECLASS_TIMER )
    {
        /* We got a tick.  Decrement counter, and if 0, send notify. */
        if( selected && !(--data->Ticks ) )
        {
            data->Ticks = 1;
            NotifyAttrChanges( obj, msg->gpi_GInfo, OPUF_INTERIM, GA_ID, ((struct Gadget *) obj)->GadgetID, TAG_DONE );
        }
    }

    {
        struct Gadget   *button = (struct Gadget *) obj;
        struct RastPort *rp;

        if( ( button->Flags & GFLG_SELECTED ) != selected )
        {
            /* Update changes in gadget render */
            button->Flags ^= GFLG_SELECTED;
            if( rp = ObtainGIRPort( msg->gpi_GInfo ) )
            {
                DoMethod( obj, GM_RENDER, msg->gpi_GInfo, rp, GREDRAW_UPDATE );
                ReleaseGIRPort( rp );
            }
        }
    }

    return retval;
}


