/**
 * Scout - The Amiga System Monitor
 *
 *------------------------------------------------------------------
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * You must not use this source code to gain profit of any kind!
 *
 *------------------------------------------------------------------
 *
 * @author Andreas Gelhausen
 * @author Richard Körber <rkoerber@gmx.de>
 */

#include "system_headers.h"

static void SetDetails( struct IClass *cl,
                        Object *obj,
                        struct ClassEntry *ce )
{
    struct ClassesDetailWinData *cdwd = INST_DATA(cl, obj);
    BOOL found = FALSE;
    struct IClass *myclass;

    if (myclass = MakeClass("« Scout Dummy Class »", "rootclass", NULL, 0, 0)) {
        struct Node *clist;

        AddClass(myclass);

        Forbid();

        for (clist = (struct Node *)&myclass->cl_Dispatcher.h_MinNode; clist->ln_Pred; clist = clist->ln_Pred);

        for (clist = clist->ln_Succ; clist->ln_Succ; clist = clist->ln_Succ) {
            if (clist == (struct Node *)myclass) continue;
            if (clist == (struct Node *)ce->ce_Addr) {
                found = TRUE;
                break;
            }
        }

        if (found) {
            struct IClass *bc = ce->ce_Addr;

            MySetContents(cdwd->cdwd_ClassesMoreText[0], "%s", ce->ce_ClassName);
            MySetContents(cdwd->cdwd_ClassesMoreText[1], "%s", ce->ce_SuperClassName);
            MySetContents(cdwd->cdwd_ClassesMoreText[2], MUIX_R "$%08lx\n" MUIX_R "$%08lx\n" MUIX_R "%lD\n" MUIX_R "%lD", bc, bc->cl_Super, bc->cl_InstOffset, bc->cl_InstSize);
            MySetContents(cdwd->cdwd_ClassesMoreText[3], MUIX_R "$%08lx\n" MUIX_R "$%08lx\n" MUIX_R "$%08lx\n" MUIX_R "$%08lx", bc->cl_Dispatcher.h_Entry, bc->cl_Dispatcher.h_SubEntry, bc->cl_Dispatcher.h_Data, bc->cl_UserData);
            MySetContents(cdwd->cdwd_ClassesMoreText[4], MUIX_R "%lD\n" MUIX_R "%lD\n" MUIX_R "$%08lx\n" MUIX_R "$%08lx", bc->cl_SubclassCount, bc->cl_ObjectCount, bc->cl_Flags, bc->cl_Reserved);

            set(obj, MUIA_Window_Title, MyGetChildWindowTitle("CLASS", ce->ce_ClassName, cdwd->cdwd_Title, sizeof(cdwd->cdwd_Title)));
        }

        Permit();

        FreeClass(myclass);
    }
}

static ULONG __saveds mNew( struct IClass *cl,
                            Object *obj,
                            struct opSet *msg )
{
    APTR classmoretext[5];

    if (obj = (Object *)DoSuperNew(cl, obj,
        MUIA_HelpNode, ClassesText,
        MUIA_Window_ID, MakeID('.','C','L','S'),
        WindowContents, VGroup,

            Child, ColGroup(2),
                Child, MyLabel2("Name:"),
                Child, classmoretext[0] = MyTextObject(),
                Child, MyLabel2("Super:"),
                Child, classmoretext[1] = MyTextObject(),
            End,

            Child, HGroup,
                Child, MyLabel2("Address:\nSuper:\nInstOffset:\nInstSize:"),
                Child, classmoretext[2] = MyTextObject2(),
                Child, HSpace(0),
                Child, MyLabel2("Entry:\nSubEntry:\nData:\nUserData:"),
                Child, classmoretext[3] = MyTextObject2(),
                Child, HSpace(0),
                Child, MyLabel2("SubClasses:\nObjects:\nFlags:\nReserved:"),
                Child, classmoretext[4] = MyTextObject2(),
            End,
        End,
        TAG_MORE, msg->ops_AttrList))
    {
        struct ClassesDetailWinData *cdwd = INST_DATA(cl, obj);
        APTR parent;

        CopyMem(classmoretext, cdwd->cdwd_ClassesMoreText, sizeof(cdwd->cdwd_ClassesMoreText));

        parent = (APTR)GetTagData(MUIA_Window_ParentWindow, (ULONG)NULL, msg->ops_AttrList);

        DoMethod(parent, MUIM_Window_AddChildWindow, obj);
        DoMethod(obj,    MUIM_Notify,              MUIA_Window_CloseRequest, TRUE, MUIV_Notify_Application, 5, MUIM_Application_PushMethod, parent, 2, MUIM_Window_RemChildWindow, obj);
    }

    return (ULONG)obj;
}

static ULONG __saveds mDispose( struct IClass *cl,
                                Object *obj,
                                struct opSet *msg )
{
    set(obj, MUIA_Window_Open, FALSE);

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

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

    for (tags = ((struct opSet *)msg)->ops_AttrList; tag = NextTagItem(&tags); ) {
        switch (tag->ti_Tag) {
            case MUIA_Window_ParentWindow:
                DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, MUIV_Notify_Application, 5, MUIM_Application_PushMethod, (APTR)tag->ti_Data, 2, MUIM_Window_RemChildWindow, obj);
                break;

            case MUIA_ClassesDetailWin_Class:
                SetDetails(cl, obj, (struct ClassEntry *)tag->ti_Data);
                break;
        }
    }

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

ULONG __asm __saveds ClassesDetailWinDispatcher( 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_DISPOSE: return (mDispose(cl, obj, (APTR)msg));
        case OM_SET:     return (mSet(cl, obj, (APTR)msg));
    }

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

