#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <workbench/icon.h>
#include <workbench/workbench.h>
#include <dos/dosextens.h>

#include "rp.h" // before icon protos

#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/icon_protos.h>
#include <clib/dos_protos.h>
#include <pragmas/icon_pragmas.h>
#include <reaction/reaction.h>
#include <gadgets/chooser.h>
#include <pragmas/chooser_pragmas.h>
#include <gadgets/string.h>
#include <pragmas/string_pragmas.h>
#include <gadgets/checkbox.h>
#include <pragmas/checkbox_pragmas.h>
#include <gadgets/layout.h>
#include <pragmas/layout_pragmas.h>
#include <gadgets/button.h>
#include <pragmas/button_pragmas.h>
#include <images/label.h>
#include <pragmas/label_pragmas.h>
#include <proto/label.h>
#include <classes/window.h>
#include <pragmas/window_pragmas.h>

#include <stdlib.h>
#include <string.h>

AGLOBAL ABOOL              quit              = FALSE;
AGLOBAL struct Gadget*     icon_gadgets[GIDS_4 + 1];
AGLOBAL struct IconStruct  icon =
{   TRUE, FALSE,
    WBDRAWER, ""
};

// from rp.c
IMPORT Object*             WinObject[FUNCTIONS + 1];
IMPORT TEXT                IOBuffer[LONGESTFIELD + 1];
IMPORT SBYTE               page;
IMPORT TEXT                asldir[PATHNAMEFIELD + 1];
IMPORT ULONG               signal;
IMPORT struct Window*      MainWindowPtr;
IMPORT struct Screen*      ScreenPtr;
IMPORT struct SharedStruct shared;
IMPORT struct Library     *ButtonBase,
                          *CheckBoxBase,
                          *ChooserBase,
                          *IconBase,
                          *LabelBase,
                          *LayoutBase,
                          *StringBase,
                          *WindowBase;
IMPORT struct Menu*        MenuPtr;
IMPORT ABOOL               done;
IMPORT TEXT                aslresult[PATHNAMEFIELD + 1];

#define ICONOPTIONS        8

MODULE ABOOL               stop;
MODULE STRPTR IconOptions[ICONOPTIONS] =
{   "Disk",
    "Drawer",
    "Tool",
    "Project",
    "Trashcan",
    "Device",
    "Kickstart",
    "AppIcon"
};
/* icon.type is the same as the values used by the system. So, the
value used by the gadget is one less than the actual value. */

AGLOBAL void icon1(void)
{   ULONG               i;
    struct List         ChooserList;
    struct ChooserNode *ChooserNodePtr[7 + 1];
    struct Hook         Hook4Struct;

    icon.pathname[0] = 0;

    NewList(&ChooserList);
    for (i = 0; i <= 7; i++)
    {   if (!(ChooserNodePtr[i] = (struct ChooserNode *) AllocChooserNode(CNA_Text, IconOptions[i], TAG_DONE)))
        {   rq("Can't allocate chooser node!");
        }
        AddTail(&ChooserList, (struct Node *) ChooserNodePtr[i]);
    } // automatically freed by ReAction at DisposeObject() time

    InitHook(&Hook4Struct, Hook4Func, NULL);

    /* Create the window object. */
    lockscreen();
    if (!(WinObject[4] =          NewObject(WINDOW_GetClass(), NULL,
    // window
    WA_PubScreen,                 ScreenPtr,
    WA_ScreenTitle,               "Report+",
    WA_Title,                     "Report+: Icon Processor",
    WA_Activate,                  TRUE,
    WA_DepthGadget,               TRUE,
    WA_DragBar,                   TRUE,
    WA_CloseGadget,               TRUE,
    WA_SizeGadget,                TRUE,
    WA_IDCMP,                     IDCMP_RAWKEY,
    WINDOW_IDCMPHook,             &Hook4Struct,
    WINDOW_IDCMPHookBits,         IDCMP_RAWKEY,
    WINDOW_MenuStrip,             MenuPtr,
    WINDOW_Position,              WPOS_CENTERSCREEN,
    WINDOW_ParentGroup,           icon_gadgets[GID_4_LY1] =
                                  NewObject(LAYOUT_GetClass(), NULL,
        // root-layout
        LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
        LAYOUT_SpaceOuter,        TRUE,
        LAYOUT_DeferLayout,       TRUE,
        LAYOUT_AddChild,          NewObject(LAYOUT_GetClass(), NULL,
            // layout
            LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
            LAYOUT_VertAlignment, LALIGN_CENTER,
            LAYOUT_HorizAlignment,LALIGN_CENTER,
            LAYOUT_BevelStyle,    BVS_NONE,
            LAYOUT_AddChild,      icon_gadgets[GID_4_CB1] =
                                  NewObject(CHECKBOX_GetClass(), NULL,
                GA_ID,                GID_4_CB1,
                GA_RelVerify,         TRUE,
                GA_Text,              "_Optimize colours?",
                GA_Selected,          (BOOL) icon.optimize,
            TAG_END),
            CHILD_WeightedHeight,     0,
            LAYOUT_AddImage,          NewObject
            (   LABEL_GetClass(),     NULL,
                LABEL_Text,           "",
                TAG_END
            ),
            CHILD_WeightedWidth,      100,
            LAYOUT_AddImage,
            NewObject
            (   LABEL_GetClass(),     NULL,
                LABEL_Text,           "_Type:",
                LABEL_Justification,  LJ_LEFT,
            TAG_END),
            CHILD_WeightedWidth,      0,
            LAYOUT_AddChild,          icon_gadgets[GID_4_CH1] =
            NewObject
            (   CHOOSER_GetClass(),   NULL,
                GA_ID,                GID_4_CH1,
                GA_RelVerify,         TRUE,
                CHOOSER_PopUp,        TRUE,
                CHOOSER_Labels,       &ChooserList,
                CHOOSER_Selected,     (WORD) (icon.type - 1),
            TAG_END),
            CHILD_WeightedWidth,      0,
        TAG_END), 
        CHILD_WeightedHeight,         0,
        LAYOUT_AddChild,              icon_gadgets[GID_4_CB2] =
                                      NewObject(CHECKBOX_GetClass(), NULL,
                // checkbox
                GA_ID,                GID_4_CB2,
                GA_RelVerify,         TRUE,
                GA_Text,              "Preserve p_lanar data?",
                GA_Selected,          (BOOL) icon.planar,
                TAG_END),
            CHILD_WeightedHeight,     0,
            LAYOUT_AddChild,          NewObject(LAYOUT_GetClass(), NULL,
                // layout
                LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
                LAYOUT_VertAlignment, LALIGN_CENTER,
                LAYOUT_HorizAlignment,LALIGN_CENTER,
                LAYOUT_BevelStyle,    BVS_NONE,
                LAYOUT_AddImage,      NewObject(LABEL_GetClass(), NULL,
                    // label
                    LABEL_Text,       "_Pathname(s):",
                    LABEL_Justification,LJ_LEFT,
                    TAG_END),
                LAYOUT_AddChild,      icon_gadgets[GID_4_ST1] =
                                      NewObject(STRING_GetClass(), NULL,
                    // string        
                    GA_ID,            GID_4_ST1,
                    GA_RelVerify,     TRUE,
                    STRINGA_TextVal,  icon.pathname,
                    STRINGA_MinVisible,20,
                    TAG_END),
                LAYOUT_AddChild,      icon_gadgets[GID_4_BU1] =
                                      NewObject(NULL, "button.gadget",
                    // button
                    GA_ID,            GID_4_BU1,
                    GA_RelVerify,     TRUE,
                    BUTTON_AutoButton,BAG_POPFILE,
                    TAG_END),
                CHILD_WeightedWidth,  0,
                TAG_END),
            CHILD_WeightedHeight,     0,
            LAYOUT_AddChild,          icon_gadgets[GID_4_ST2] =
                                      NewObject(STRING_GetClass(), NULL,
                // string        
                GA_ReadOnly,          TRUE,
                GA_ID,                GID_4_ST2,
                STRINGA_TextVal,      "Ready.",
                TAG_END),
            CHILD_WeightedHeight,     0,
            LAYOUT_AddChild,          NewObject(LAYOUT_GetClass(), NULL,
                // layout
                LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
                LAYOUT_VertAlignment, LALIGN_CENTER,
                LAYOUT_HorizAlignment,LALIGN_CENTER,
                LAYOUT_BevelStyle,    BVS_NONE,
                LAYOUT_AddChild,      icon_gadgets[GID_4_BU3] =
                                      NewObject(NULL, "button.gadget",
                    // button
                    GA_ID,            GID_4_BU3,
                    GA_RelVerify,     TRUE,
                    GA_Text,          "Pro_cess",
                TAG_END),
                CHILD_WeightedWidth,  50,
                LAYOUT_AddChild,      icon_gadgets[GID_4_BU4] =
                                      NewObject(NULL, "button.gadget",
                    // button
                    GA_ID,            GID_4_BU4,
                    GA_RelVerify,     TRUE,
                    GA_Text,          "Stop",
                    GA_Disabled,      TRUE,
                    TAG_END),
                CHILD_WeightedWidth,  50,
                TAG_END),
            CHILD_WeightedHeight,     0,
            TAG_END),
    TAG_END)
    ))
    {   rq("Can't create ReAction objects!");
    }
    unlockscreen();
    openwindow();
    ActivateLayoutGadget(icon_gadgets[GID_4_LY1], MainWindowPtr, NULL, (Object) icon_gadgets[GID_4_ST1]);
    loop();
    closewindow();
    if (quit)
    {   cleanexit(EXIT_SUCCESS);
}   }

AGLOBAL void icon_do(void)
{   ABOOL  anyfound;
    STRPTR stringptr;

    if (!(GetAttr
    (   CHOOSER_Selected, icon_gadgets[GID_4_CH1], (ULONG *) &(icon.type)
    )))
    {   rq("Unsupported inquiry!"); // should never happen
    }
    icon.type++;

    if (!(GetAttr
    (   STRINGA_TextVal, icon_gadgets[GID_4_ST1], (ULONG *) &stringptr
    )))
    {   rq("Unsupported inquiry!"); // should never happen
    }
    strcpy(icon.pathname, stringptr);

    if (!(GetAttr
    (   GA_Selected, icon_gadgets[GID_4_CB1], (ULONG *) &(icon.optimize)
    )))
    {   rq("Unsupported inquiry!"); // should never happen
    }
    if (!(GetAttr
    (   GA_Selected, icon_gadgets[GID_4_CB2], (ULONG *) &(icon.planar)
    )))
    {   rq("Unsupported inquiry!"); // should never happen
    }

    SetGadgetAttrs
    (   icon_gadgets[GID_4_CH1], MainWindowPtr, NULL,
        GA_Disabled, TRUE,
        TAG_END
    );
    SetGadgetAttrs
    (   icon_gadgets[GID_4_CB1], MainWindowPtr, NULL,
        GA_Disabled, TRUE,
        TAG_END
    );
    SetGadgetAttrs
    (   icon_gadgets[GID_4_CB2], MainWindowPtr, NULL,
        GA_Disabled, TRUE,
        TAG_END
    );
    SetGadgetAttrs
    (   icon_gadgets[GID_4_ST1], MainWindowPtr, NULL,
        GA_Disabled, TRUE,
        TAG_END
    );
    SetGadgetAttrs
    (   icon_gadgets[GID_4_BU1], MainWindowPtr, NULL,
        GA_Disabled, TRUE,
        TAG_END
    );
    SetGadgetAttrs
    (   icon_gadgets[GID_4_BU3], MainWindowPtr, NULL,
        GA_Disabled, TRUE,
        TAG_END
    );
    SetGadgetAttrs
    (   icon_gadgets[GID_4_BU4], MainWindowPtr, NULL,
        GA_Disabled, FALSE,
        TAG_END
    );
    SetAttrs
    (   WinObject[4],
        WA_BusyPointer, TRUE,
        TAG_END
    );
                          
    strcpy(shared.pathname, icon.pathname);
    anyfound = convert(TRUE);
    strcpy(icon.pathname, shared.pathname);

    if (!stop)
    {   if (anyfound)
        {   SetGadgetAttrs
            (   icon_gadgets[GID_4_ST2], MainWindowPtr, NULL,
                STRINGA_TextVal, "All done.",
            TAG_END);
        } else
        {   SetGadgetAttrs
            (   icon_gadgets[GID_4_ST2], MainWindowPtr, NULL,
                STRINGA_TextVal, "No matches!",
            TAG_END);
    }   }
    SetAttrs
    (   WinObject[4],
        WA_BusyPointer, FALSE,
        TAG_END
    );
    SetGadgetAttrs
    (   icon_gadgets[GID_4_CH1], MainWindowPtr, NULL,
        GA_Disabled, FALSE,
        TAG_END
    );
    SetGadgetAttrs
    (   icon_gadgets[GID_4_CB1], MainWindowPtr, NULL,
        GA_Disabled, FALSE,
        TAG_END
    );
    SetGadgetAttrs
    (   icon_gadgets[GID_4_CB2], MainWindowPtr, NULL,
        GA_Disabled, FALSE,
        TAG_END
    );
    SetGadgetAttrs
    (   icon_gadgets[GID_4_ST1], MainWindowPtr, NULL,
        GA_Disabled, FALSE,
        TAG_END
    );
    SetGadgetAttrs
    (   icon_gadgets[GID_4_BU1], MainWindowPtr, NULL,
        GA_Disabled, FALSE,
        TAG_END
    );
    SetGadgetAttrs
    (   icon_gadgets[GID_4_BU3], MainWindowPtr, NULL,
        GA_Disabled, FALSE,
        TAG_END
    );
    SetGadgetAttrs
    (   icon_gadgets[GID_4_BU4], MainWindowPtr, NULL,
        GA_Disabled, TRUE,
        TAG_END
    );
}

AGLOBAL void iconconvert(ABOOL gui)
{   TEXT               saystring[LONGFIELD + 1];
    ULONG              length = strlen(shared.thisfile);
    struct DiskObject* IconPtr;

    if (length <= 5) // in case we get passed an empty string
    {   return;
    }
    if (!stricmp(&(shared.thisfile[length - 5]), ".info"))
    {   shared.thisfile[length - 5] = 0;
    }
   
    strcpy(saystring, "Processing ");
    strcat(saystring, shared.thisfile);
    strcat(saystring, ".info...");
    if (gui)
    {   SetGadgetAttrs
        (   icon_gadgets[GID_4_ST2], MainWindowPtr, NULL,
            STRINGA_TextVal, saystring,
            TAG_END
        );
    } else
    {   Printf("%s", saystring);
        Flush(Output());
        saystring[0] = 0;
    }

    if (IconPtr = GetIconTags(shared.thisfile, TAG_DONE))
    {   IconPtr->do_Type = (UWORD) icon.type;
        if (PutIconTags(shared.thisfile, IconPtr,
            ICONPUTA_NotifyWorkbench,     TRUE,
            ICONPUTA_DropPlanarIconImage, (BOOL) !icon.planar,
            ICONPUTA_OptimizeImageSpace,  (BOOL) icon.optimize,
            TAG_DONE
        ))
        {   strcat(saystring, "done.");
        } else strcat(saystring, "failed to write!");
        FreeDiskObject(IconPtr);
    } else strcat(saystring, "failed to read!");

    if (gui)
    {   SetGadgetAttrs
        (   icon_gadgets[GID_4_ST2], MainWindowPtr, NULL,
            STRINGA_TextVal, saystring,
            TAG_END
        );
    } else
    {   Printf("%s\n", saystring);
    }

    checkabort(gui);
}

AGLOBAL void icon_loop(ULONG gid)
{   STRPTR stringptr;

    switch (gid)
    {
    case GID_4_CH1:
        if (!(GetAttr
        (   CHOOSER_Selected, icon_gadgets[GID_4_CH1], (ULONG *) &(icon.type)
        )))
        {   rq("Unsupported inquiry!"); // should never happen
        }
        icon.type++;
    break;
    case GID_4_ST1:
        if (!(GetAttr
        (   STRINGA_TextVal, icon_gadgets[GID_4_ST1], (ULONG *) &stringptr
        )))
        {   rq("Unsupported inquiry!"); // should never happen
        }
        strcpy(icon.pathname, stringptr);
    break;
    case GID_4_BU1:
        strcpy(shared.pathname, icon.pathname);
        multiasl("#?.info");
        strcpy(icon.pathname, shared.pathname);
        SetGadgetAttrs
        (   icon_gadgets[GID_4_ST1], MainWindowPtr, NULL,
            STRINGA_TextVal, icon.pathname,
            TAG_END
        );
    break;
    case GID_4_BU3:
        icon_do();
    break;
    case GID_4_CB1:
        if (!(GetAttr
        (   GA_Selected, icon_gadgets[GID_4_CB1], (ULONG *) &(icon.optimize)
        )))
        {   rq("Unsupported inquiry!"); // should never happen
        }
    break;
    case GID_4_CB2:
        if (!(GetAttr
        (   GA_Selected, icon_gadgets[GID_4_CB2], (ULONG *) &(icon.planar)
        )))
        {   rq("Unsupported inquiry!"); // should never happen
        }
    break;
    default:
    break;
}   }

AGLOBAL ULONG Hook4Func(struct Hook *h, VOID *o, VOID *msg)
{   /* "When the hook is called, the data argument points to the 
    window object and message argument to the IntuiMessage." */

    UWORD code, qual;

    geta4(); // wait till here before doing anything

    code = ((struct IntuiMessage *) msg)->Code;
    qual = ((struct IntuiMessage *) msg)->Qualifier;

    switch(code)
    {
    case SCAN_HELP:
        helpabout();
    break;
    case SCAN_ESCAPE:
        if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
        {   cleanexit(EXIT_SUCCESS);
        } else page = 0;
    break;
    case SCAN_P:
        ActivateLayoutGadget(icon_gadgets[GID_4_LY1], MainWindowPtr, NULL, (Object) icon_gadgets[GID_4_ST1]);
    break;
    case SCAN_T:
        if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
        {   if (icon.type == 1)
            {   icon.type = ICONOPTIONS;
            } else icon.type--;
        } else
        {   if (icon.type == ICONOPTIONS)
            {   icon.type = 1;
            } else icon.type++;
        }

        SetGadgetAttrs
        (   icon_gadgets[GID_4_CH1], MainWindowPtr, NULL,
            CHOOSER_Selected, icon.type - 1,
            TAG_END
        );
    break;
    case SCAN_PERIOD:
        strcpy(shared.pathname, icon.pathname);
        multiasl("#?.info");
        strcpy(icon.pathname, shared.pathname);
        SetGadgetAttrs
        (   icon_gadgets[GID_4_ST1], MainWindowPtr, NULL,
            STRINGA_TextVal, icon.pathname,
            TAG_END
        );
    break;
    default:
    break;
    }

    return(1);
}

AGLOBAL void icon_die(void)
{   IOBuffer[16] = (UBYTE) icon.type;
    IOBuffer[17] = (UBYTE) icon.optimize;
    IOBuffer[18] = (UBYTE) icon.planar;
}

AGLOBAL void icon_config(void)
{   icon.type     = (ULONG) IOBuffer[16];
    icon.optimize = (ULONG) IOBuffer[17];
    icon.planar   = (ULONG) IOBuffer[18];
}

