/**
 * 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 struct MaskedLongFlag portFlags[] = {
    { PA_SIGNAL,  PF_ACTION, "PA_SIGNAL",  "0" },
    { PA_SOFTINT, PF_ACTION, "PA_SOFTINT", "1" },
    { PA_IGNORE,  PF_ACTION, "PA_IGNORE",  "2" },
    { 0,          0,         NULL,         NULL }
};

static void SetDetails( struct IClass *cl,
                        Object *obj,
                        struct PortEntry *pe )
{
    struct PortsDetailWinData *pdwd = INST_DATA(cl, obj);
    struct MsgPort *mp = pe->pe_Addr;
    UBYTE flags[16];

    Flags2BinStr(mp->mp_Flags, flags, sizeof(flags));

    MySetContentsHealed(pdwd->pdwd_PortMoreText[0], "%s", mp->mp_Node.ln_Name);
    MySetContents(pdwd->pdwd_PortMoreText[1], MUIX_R "$%08lx\n" MUIX_C "%ld\n" MUIX_C "%s", mp, mp->mp_Node.ln_Pri, GetNodeType(mp->mp_Node.ln_Type));
    MySetContents(pdwd->pdwd_PortMoreText[2], MUIX_B "%s", flags);
    MySetContents(pdwd->pdwd_PortMoreText[3], MUIX_C "%ld\n" MUIX_R "$%08lx", mp->mp_SigBit, mp->mp_SigTask);
    MySetContentsHealed(pdwd->pdwd_PortMoreText[4], "%s", nonetest(GetTaskName(mp->mp_SigTask)));
    MySetContents(pdwd->pdwd_PortMoreText[5], MUIX_R "$%08lx\n$%08lx", &mp->mp_MsgList, mp->mp_MsgList.lh_Head);
    MySetContents(pdwd->pdwd_PortMoreText[6], MUIX_R "$%08lx\n$%08lx", mp->mp_MsgList.lh_Tail, mp->mp_MsgList.lh_TailPred);

    set(obj, MUIA_Window_Title, MyGetChildWindowTitle("PORT", pe->pe_Name, pdwd->pdwd_Title, sizeof(pdwd->pdwd_Title)));
}

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

    if (obj = (Object *)DoSuperNew(cl, obj,
        MUIA_HelpNode, PortsText,
        MUIA_Window_ID, MakeID('.','P','O','R'),
        WindowContents, HGroup,
            Child, VGroup, MUIA_Group_SameWidth, TRUE,
                Child, MyLabel2("Name:"),
                Child, MyVSpace(0),
                Child, MyLabel2("Address:\nPri:\nType:"),
                Child, MyVSpace(0),
                Child, MyLabel2("TaskName:"),
                Child, MyLabel2("MsgList:\nHead:"),
            End,
            Child, VGroup, MUIA_Group_SameWidth, TRUE,
                Child, portmoretext[0] = MyTextObject(),
                Child, HGroup,
                    Child, portmoretext[1] = MyTextObject2(),
                    Child, VGroup,
                        Child, MyLabel("Flags:"),
                        Child, MyLabel("SigBit:\nSigTask:"),
                    End,
                    Child, VGroup, MUIA_Group_SameWidth, TRUE, MUIA_Weight, 0,
                        Child, portmoretext[2] = MakeButton(""),
                        Child, portmoretext[3] = MyTextObject(),
                    End,
                End,
                Child, portmoretext[4] = MyTextObject(),
                Child, HGroup,
                    Child, portmoretext[5] = MyTextObject2(),
                    Child, MyLabel ("Tail:\nTailPred:"),
                    Child, portmoretext[6] = MyTextObject2(),
                End,
            End,
        End,
        TAG_MORE, msg->ops_AttrList))
    {
        struct PortsDetailWinData *pdwd = INST_DATA(cl, obj);
        APTR parent;

        CopyMem(portmoretext, pdwd->pdwd_PortMoreText, sizeof(pdwd->pdwd_PortMoreText));

        set(obj, MUIA_Window_ActiveObject, portmoretext[2]);

        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);
        DoMethod(portmoretext[2], MUIM_Notify,              MUIA_Pressed            , FALSE, obj,                     1, MUIM_PortsDetailWin_PortFlagsMore);
    }

    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 PortsDetailWinData *pdwd = INST_DATA(cl, obj);
    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, tag->ti_Data, 2, MUIM_Window_RemChildWindow, obj);
                break;

            case MUIA_PortsDetailWin_Port:
                pdwd->pdwd_Port = (struct PortEntry *)tag->ti_Data;
                SetDetails(cl, obj, (struct PortEntry *)tag->ti_Data);
                break;
        }
    }

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

static ULONG __saveds mPortsFlagsMore( struct IClass *cl,
                                       Object *obj,
                                       Msg msg )
{
    struct PortsDetailWinData *pdwd = INST_DATA(cl, obj);
    APTR flagsWin;

    if (flagsWin = FlagsWindowObject,
            MUIA_Window_Title, "Port Flags",
            MUIA_Window_ParentWindow, obj,
        End) {
        DoMethod(flagsWin, MUIM_FlagsWin_ShowFlags, pdwd->pdwd_Port->pe_Addr->mp_Flags, MUIV_FlagsWin_FlagsType_Byte, NULL, portFlags, "mp_Flags");
    }

    return 0;
}

ULONG __asm __saveds PortsDetailWinDispatcher( 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));
        case MUIM_PortsDetailWin_PortFlagsMore: return (mPortsFlagsMore(cl, obj, (APTR)msg));
    }

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

