#include "system_headers.h"

#define FD_EXAMPLE_TEXT "дв the quick brown fox jumps over the lazy dog"

// extern void kprintf(char *, ...);

static ULONG __saveds mNew( struct IClass *cl,
                            Object *obj,
                            Msg msg )
{
    struct FontDisplayData *fdd;
    struct TagItem *tags, *tag;

    if (!(obj = (Object *)DoSuperMethodA(cl, obj, msg)))
        return(0);

    fdd = INST_DATA(cl, obj);

    /* parse initial taglist */

    for (tags = ((struct opSet *)msg)->ops_AttrList; tag=NextTagItem(&tags); ) {
        switch (tag->ti_Tag) {
            case FDATTR_Font:
                if (tag->ti_Data) fdd->fdd_Font = (struct TextFont *)tag->ti_Data;
                break;
        }
    }

    return (ULONG)obj;
}

static ULONG __saveds mSet( struct IClass *cl,
                            Object *obj,
                            Msg msg )
{
    struct FontDisplayData *fdd = INST_DATA(cl, obj);
    struct TagItem *tags, *tag;

    for (tags = ((struct opSet *)msg)->ops_AttrList; tag = NextTagItem(&tags); ) {
        switch (tag->ti_Tag) {
            case FDATTR_Font:
                if (tag->ti_Data) {
                    fdd->fdd_Font = (struct TextFont *)tag->ti_Data;
                    MUI_Redraw(obj, MADF_DRAWOBJECT); /* redraw ourselves completely */
                }
                break;
        }
    }

    return (DoSuperMethodA(cl,obj,msg));
}


static ULONG __saveds mGet( struct IClass *cl,
                            Object *obj,
                            Msg msg )
{
    struct FontDisplayData *fdd = INST_DATA(cl, obj);
    ULONG *store = ((struct opGet *)msg)->opg_Storage;

    switch (((struct opGet *)msg)->opg_AttrID)
    {
        case FDATTR_Font: *store = (ULONG)fdd->fdd_Font; return (TRUE);
    }

    return (DoSuperMethodA(cl, obj, msg));
}


static ULONG __saveds mAskMinMax( struct IClass *cl,
                                  Object *obj,
                                  struct MUIP_AskMinMax *msg )
{
    DoSuperMethodA(cl, obj, msg);

    msg->MinMaxInfo->MinWidth  += 100;
    msg->MinMaxInfo->DefWidth  += 100;
    msg->MinMaxInfo->MaxWidth  += 1000;

    msg->MinMaxInfo->MinHeight += 60;
    msg->MinMaxInfo->DefHeight += 60;
    msg->MinMaxInfo->MaxHeight += 60;

    return(0);
}

static ULONG __saveds mDraw( struct IClass *cl,
                             Object *obj,
                             struct MUIP_Draw *msg )
{
    struct FontDisplayData *fdd = INST_DATA(cl, obj);

    // kprintf("FontDisplayClass: mDraw()\n");

    DoSuperMethodA(cl, obj, msg);

    // kprintf("FontDisplayClass: fdd_Font = %08lx\n", fdd->fdd_Font);
    if (fdd->fdd_Font) {
        struct Region *newRegion;

        // kprintf("FontDisplayClass: %s/%ld\n", fdd->fdd_Font->tf_Message.mn_Node.ln_Name, fdd->fdd_Font->tf_YSize);

        SetFont(_rp(obj), fdd->fdd_Font);
        SetAPen(_rp(obj), 1);

        if (newRegion = NewRegion()) {
            struct Rectangle rect;
            struct Region *oldRegion;

            rect.MinX = _mleft(obj);
            rect.MaxX = _mright(obj);
            rect.MinY = _mtop(obj);
            rect.MaxY = _mbottom(obj);
            OrRectRegion(newRegion, &rect);

            // kprintf("FontDisplayClass: displaying in rect (%ld, %ld) - (%ld, %ld)\n", rect.MinX, rect.MinY, rect.MaxX, rect.MaxY);
            oldRegion = InstallClipRegion(_window(obj)->WLayer, newRegion);
            if (fdd->fdd_Font->tf_YSize > _mheight(obj)) {
                Move(_rp(obj), _mleft(obj), _mtop(obj) + fdd->fdd_Font->tf_Baseline);
            } else {
                Move(_rp(obj), _mleft(obj), _mtop(obj) + ((_mheight(obj) - fdd->fdd_Font->tf_YSize) / 2) + fdd->fdd_Font->tf_Baseline);
            }
            Text(_rp(obj), FD_EXAMPLE_TEXT, strlen(FD_EXAMPLE_TEXT));
            InstallClipRegion(_window(obj)->WLayer, oldRegion);
        }
    }

    return(0);
}

ULONG __asm __saveds FontDisplayDispatcher( register __a0 struct IClass *cl,
                                            register __a2 Object *obj,
                                            register __a1 Msg msg )
{
    switch (msg->MethodID) {
        case OM_NEW        : return (mNew      (cl, obj, (APTR)msg));
        case OM_SET        : return (mSet      (cl, obj, (APTR)msg));
        case OM_GET        : return (mGet      (cl, obj, (APTR)msg));
        case MUIM_AskMinMax: return (mAskMinMax(cl, obj, (APTR)msg));
        case MUIM_Draw     : return (mDraw     (cl, obj, (APTR)msg));
    }

    return (DoSuperMethodA(cl, obj, msg));
}

