/**
 * 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"

struct LongFlag resourceFlags[] = {
    { LIBF_SUMMING, "LIBF_SUMMING", "%00000001" },
    { LIBF_CHANGED, "LIBF_CHANGED", "%00000010" },
    { LIBF_SUMUSED, "LIBF_SUMUSED", "%00000100" },
    { LIBF_DELEXP,  "LIBF_DELEXP",  "%00001000" },
    { 0,            NULL,           NULL }
};

__asm __saveds LONG fselist_con2func(register __a2 Object *obj, register __a1 struct NList_ConstructMessage *msg, register __a0 struct Hook *hook)
{
    return AllocListEntry(msg->pool, msg->entry, sizeof(struct FileSystemEntry));
}

MakeHook(fselist_con2hook, fselist_con2func);

__asm __saveds LONG fselist_des2func(register __a2 Object *obj, register __a1 struct NList_DestructMessage *msg, register __a0 struct Hook *hook)
{
    FreeListEntry(msg->pool, &msg->entry);

    return 0;
}

MakeHook(fselist_des2hook, fselist_des2func);

__asm __saveds LONG fselist_dsp2func(register __a2 Object *obj, register __a1 struct NList_DisplayMessage *msg, register __a0 struct Hook *hook)
{
    struct FileSystemEntry *fse = (struct FileSystemEntry *)msg->entry;

    if (fse) {
        msg->strings[0] = fse->fse_FileSystem;
        msg->strings[1] = fse->fse_DosType;
        msg->strings[2] = fse->fse_Version;
        msg->strings[3] = fse->fse_Creator;
    } else {
        msg->strings[0] = MUIX_B "FileSystem";
        msg->strings[1] = MUIX_B "fse_DosType";
        msg->strings[2] = MUIX_B "fse_Version";
        msg->strings[3] = MUIX_B "fse_Creator";
    }

    return 0;
}

MakeHook(fselist_dsp2hook, fselist_dsp2func);

static LONG fselist_cmp2colfunc( struct FileSystemEntry *fse1,
                                 struct FileSystemEntry *fse2,
                                 ULONG column )
{
    switch (column) {
        case 0: return stricmp(fse1->fse_FileSystem, fse2->fse_FileSystem);
        case 1: return stricmp(fse1->fse_DosType, fse2->fse_DosType);
        case 2: return stricmp(fse1->fse_Version, fse2->fse_Version);
        case 3: return stricmp(fse1->fse_Creator, fse2->fse_Creator);
    }
}

__asm __saveds LONG fselist_cmp2func(register __a2 Object *obj, register __a1 struct NList_CompareMessage *msg, register __a0 struct Hook *hook)
{
    LONG cmp;
    struct FileSystemEntry *fse1, *fse2;
    ULONG col1, col2;

    fse1 = (struct FileSystemEntry *)msg->entry1;
    fse2 = (struct FileSystemEntry *)msg->entry2;
    col1 = msg->sort_type & MUIV_NList_TitleMark_ColMask;
    col2 = msg->sort_type2 & MUIV_NList_TitleMark2_ColMask;

    if (msg->sort_type == MUIV_NList_SortType_None) return 0;

    if (msg->sort_type & MUIV_NList_TitleMark_TypeMask) {
        cmp = fselist_cmp2colfunc(fse2, fse1, col1);
    } else {
        cmp = fselist_cmp2colfunc(fse1, fse2, col1);
    }

    if (cmp != 0 || col1 == col2) return cmp;

    if (msg->sort_type2 & MUIV_NList_TitleMark2_TypeMask) {
        cmp = fselist_cmp2colfunc(fse2, fse1, col2);
    } else {
        cmp = fselist_cmp2colfunc(fse1, fse2, col2);
    }

    return cmp;
}

MakeHook(fselist_cmp2hook, fselist_cmp2func);

static void SetDetails( struct IClass *cl,
                        Object *obj,
                        struct ResourceEntry *re )
{
    struct ResourcesDetailWinData *rdwd = INST_DATA(cl, obj);
    struct Library *lib = re->re_Addr;

    if (strcmp(re->re_Name, FSRNAME) == 0) {
        APTR subgroup;
        APTR resmoretext0, resmoretext1, resmoretext2, resmoretext3;
        APTR fsrlist;
        struct FileSysResource *fsr;
        struct FileSysEntry *fse;

        fsr = (struct FileSysResource *)lib;

        Child, subgroup = VGroup,
            Child, HGroup,
                Child, VGroup, MUIA_Group_SameWidth, TRUE,
                    Child, MyLabel2("Name:"),
                    Child, MyLabel2("Address:\nPri:"),
                    Child, MyLabel2("fsr_Creator:"),
                End,
                Child, VGroup,
                    Child, resmoretext0 = MyTextObject(),
                    Child, HGroup,
                        Child, resmoretext1 = MyTextObject(),
                        Child, VGroup,
                            Child, MyLabel("Type:"),
                        End,
                        Child, resmoretext2 = MyTextObject(),
                    End,
                    Child, resmoretext3 = MyTextObject(),
                End,
            End,
            Child, VGroup,
                Child, HGroup,
                    Child, MyHSpace(0),
                    Child, MyLabel2 ("fsr_FileSysEntries:"),
                    Child, MyHSpace(0),
                End,
                Child, fsrlist = MyNListviewObject(MakeID('F','S','L','V'), "BAR P=" MUIX_C ",BAR P=" MUIX_C ",BAR P=" MUIX_C ",", &fselist_con2hook, &fselist_des2hook, &fselist_dsp2hook, &fselist_cmp2hook, FALSE),
            End,
        End,

        DoMethod(rdwd->rdwd_MainGroup, OM_ADDMEMBER, subgroup);

        MySetContentsHealed(resmoretext0, "%s", lib->lib_Node.ln_Name);
        MySetContents(resmoretext1, MUIX_C "$%08lx\n%ld", lib, lib->lib_Node.ln_Pri);
        MySetContents(resmoretext2, MUIX_C "%s", GetNodeType(lib->lib_Node.ln_Type));
        MySetContentsHealed(resmoretext3, "%s", fsr->fsr_Creator);

        ApplicationSleep(TRUE);

        set(fsrlist, MUIA_NList_Quiet, TRUE);
        DoMethod(fsrlist, MUIM_NList_Clear);

        for (fse = (struct FileSysEntry *)fsr->fsr_FileSysEntries.lh_Head; fse->fse_Node.ln_Succ; fse = (struct FileSysEntry *)fse->fse_Node.ln_Succ) {
            struct FileSystemEntry fe;

            stccpy(fe.fse_FileSystem, GetDiskType((LONG *)&fse->fse_DosType), sizeof(fe.fse_FileSystem));
            _snprintf(fe.fse_DosType, sizeof(fe.fse_DosType), "$%08lx", fse->fse_DosType);
            _snprintf(fe.fse_Version, sizeof(fe.fse_Version), "%ld.%ld", fse->fse_Version >> 16, fse->fse_Version & 0xffff);
            stccpy(fe.fse_Creator, nonetest(fse->fse_Node.ln_Name), sizeof(fe.fse_Creator));
            healstring(fe.fse_Creator);

            InsertBottomEntry(fsrlist, &fe);
        }

        set(fsrlist, MUIA_NList_Quiet, FALSE);

        ApplicationSleep(FALSE);

        DoMethod(fsrlist, MUIM_NList_Sort3, MUIV_NList_Sort3_SortType_1, MUIV_NList_SortTypeAdd_None, MUIV_NList_Sort3_SortType_Both);

        set(obj, MUIA_Window_ActiveObject, fsrlist);
    } else if (strcmp(re->re_Name, CARDRESNAME) == 0 || strcmp(re->re_Name, KEYMAPRESNAME) == 0) {
        APTR subgroup;
        APTR resmoretext0, resmoretext1, resmoretext2;

        Child, subgroup = HGroup,
            Child, VGroup, MUIA_Group_SameWidth, TRUE,
                Child, MyLabel2("Name:"),
                Child, MyLabel2("Address:\nPri:"),
            End,
            Child, VGroup,
                Child, resmoretext0 = MyTextObject(),
                Child, HGroup,
                    Child, resmoretext1 = MyTextObject(),
                    Child, VGroup,
                        Child, MyLabel("Type:"),
                    End,
                    Child, resmoretext2 = MyTextObject(),
                End,
            End,
        End;

        DoMethod(rdwd->rdwd_MainGroup, OM_ADDMEMBER, subgroup);

        MySetContentsHealed(resmoretext0, "%s", lib->lib_Node.ln_Name);
        MySetContents(resmoretext1, MUIX_C "$%08lx\n%ld", lib, lib->lib_Node.ln_Pri);
        MySetContents(resmoretext2, MUIX_C "%s", GetNodeType(lib->lib_Node.ln_Type));
    } else {
        APTR subgroup, subgroup0, subgroup1;
        APTR resmoretext0, resmoretext1, resmoretext2, resmoretext3, resmoretext4;
        UBYTE flags[16];

        Child, subgroup = HGroup,
            Child, subgroup0 = VGroup, MUIA_Group_SameWidth, TRUE,
                Child, MyLabel2("Name:"),
                Child, VSpace(0),
                Child, MyLabel2("Address:\nPri:\nType:\nVersion:\nOpenCnt:"),
                Child, VSpace(0),
                Child, MyLabel2("IdString:"),
            End,
            Child, subgroup1 = VGroup,
                Child, resmoretext0 = MyTextObject(),
                Child, HGroup,
                    Child, resmoretext1 = MyTextObject(),
                    Child, VGroup,
                        Child, MyLabel("Flags:"),
                        Child, MyLabel("NegSize:\nPosSize:\nSum:\nRamPtrCnt:"),
                    End,
                    Child, VGroup,
                        Child, resmoretext2 = MakeButton(""),
                        Child, resmoretext3 = MyTextObject(),
                    End,
                End,
                Child, resmoretext4 = MyTextObject(),
            End,
        End;

        DoMethod(rdwd->rdwd_MainGroup, OM_ADDMEMBER, subgroup);

        Flags2BinStr(lib->lib_Flags, flags, sizeof(flags));

        MySetContentsHealed(resmoretext0, "%s", lib->lib_Node.ln_Name);
        MySetContents(resmoretext1, MUIX_C "$%08lx\n%ld\n%s\n%ld.%ld\n%lD", lib, lib->lib_Node.ln_Pri, GetNodeType(lib->lib_Node.ln_Type), lib->lib_Version, lib->lib_Revision, lib->lib_OpenCnt);
        MySetContents(resmoretext2, MUIX_B "%s", flags);
        MySetContents(resmoretext3, MUIX_C "%lD\n%lD\n$%08lx\n%s", lib->lib_NegSize, lib->lib_PosSize, lib->lib_Sum, re->re_RAMPtrCount);
        MySetContentsHealed(resmoretext4, "%s", nonetest(lib->lib_IdString));

        DoMethod(resmoretext2, MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, MUIM_ResourcesDetailWin_ResourceFlagsMore);

        set(obj, MUIA_Window_ActiveObject, resmoretext2);

        if (strcmp(re->re_Name, DISKNAME) == 0) {
            APTR subgroup2, subgroup3;
            struct DiscResource *dr = (struct DiscResource *)lib;
            ULONG i;
            UBYTE tmp[64];
            static UBYTE drflags[] = { DRF_ALLOC0, DRF_ALLOC1, DRF_ALLOC2, DRF_ALLOC3, DRF_ACTIVE, 0 };
            static UBYTE *drflagstext[] = { "ALLOC0", "ALLOC1", "ALLOC2", "ALLOC3", "ACTIVE" };

            Child, subgroup2 = VGroup, MUIA_Group_SameWidth, TRUE,
                Child, MyLabel2("dr_Current:"),
                Child, MyLabel2("dr_CurrTask:"),
            End,
            Child, subgroup3 = VGroup,
                Child, resmoretext0 = MyTextObject(),
                Child, resmoretext1 = MyTextObject(),
            End;

            tmp[0] = 0x00;
            i = 0;
            while (drflags[i]) {
                if (dr->dr_Flags & drflags[i]) {
                    if (strlen(tmp)) _strcatn(tmp, ", ", sizeof(tmp));
                    _strcatn(tmp, drflagstext[i], sizeof(tmp));
                }
                i++;
            }

            DoMethod(subgroup0, OM_ADDMEMBER, subgroup2);
            DoMethod(subgroup1, OM_ADDMEMBER, subgroup3);

            MySetContents(resmoretext0, "%s", tmp);
            MySetContents(resmoretext1, "%s", GetTaskName(dr->dr_CurrTask));
        }
    }

    set(obj, MUIA_Window_Title, MyGetChildWindowTitle("RESOURCE", re->re_Name, rdwd->rdwd_Title, sizeof(rdwd->rdwd_Title)));
}

static ULONG __saveds mNew( struct IClass *cl,
                            Object *obj,
                            struct opSet *msg )
{
    APTR maingroup;

    if (obj = (Object *)DoSuperNew(cl, obj,
        MUIA_HelpNode, ResourcesText,
        MUIA_Window_ID, MakeID('.','R','E','C'),
        WindowContents, maingroup = VGroup,
        End,
        TAG_MORE, msg->ops_AttrList))
    {
        struct ResourcesDetailWinData *rdwd = INST_DATA(cl, obj);
        APTR parent;

        rdwd->rdwd_MainGroup = maingroup;

        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 ResourcesDetailWinData *rdwd = 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, (APTR)tag->ti_Data, 2, MUIM_Window_RemChildWindow, obj);
                break;

            case MUIA_ResourcesDetailWin_Resource:
                rdwd->rdwd_Resource = (struct ResourceEntry *)tag->ti_Data;
                SetDetails(cl, obj, (struct ResourceEntry *)tag->ti_Data);
                break;
        }
    }

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

static ULONG __saveds mResourceFlagsMore( struct IClass *cl,
                                          Object *obj,
                                          Msg msg )
{
    struct ResourcesDetailWinData *rdwd = INST_DATA(cl, obj);
    APTR flagsWin;

    if (flagsWin = FlagsWindowObject,
            MUIA_Window_Title, "Resource Flags",
            MUIA_Window_ParentWindow, obj,
        End) {
        DoMethod(flagsWin, MUIM_FlagsWin_ShowFlags, rdwd->rdwd_Resource->re_Addr->lib_Flags, MUIV_FlagsWin_FlagsType_Byte, resourceFlags, NULL, "lib_Flags");
    }

    return 0;
}

ULONG __asm __saveds ResourcesDetailWinDispatcher( 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_ResourcesDetailWin_ResourceFlagsMore: return (mResourceFlagsMore(cl, obj, (APTR)msg));
    }

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

