#include <exec/types.h>
#include <intuition/intuition.h>
#include <libraries/gadtools.h>
#include <libraries/resource.h>
#include <resources/battmem.h>

#include <stdlib.h>
#include "amigan.h"

#define BOXLEFTX         48
#define BOXRIGHTX        (BOXLEFTX + 10 + (32 * 8))
#define BOXTOPY          24
#define BOXBOTTOMY       (BOXTOPY + 6 + (8 * 8))

MODULE struct Gadget  *BU91_Revert         = NULL,
                      *BU91_Write          = NULL,
                      *CB91_SharedAmnesia  = NULL,
                      *IN91_SCSIHostID     = NULL,
                      *CB91_SCSISyncXfer   = NULL,
                      *CB91_SCSIFastSync   = NULL,
                      *CB91_SCSITagQueues  = NULL,
                      *CB91_AmigaAmnesia   = NULL,
                      *CB91_SCSITimeout    = NULL,
                      *CB91_SCSILUNS       = NULL;

AGLOBAL ULONG              hostid, oldhostid;
IMPORT  struct VisualInfo* VisualInfoPtr;
MODULE  UBYTE              BattBuffer[32];
AGLOBAL struct Resource*   BattMemBase     = NULL;

// from rp1.c
IMPORT SBYTE               page;
IMPORT struct NewGadget*   Gadget;
IMPORT struct Gadget      *BU99_Right,
                          *ST99_Output,
                          *BU99_OutputASL,
                          *PrevGadPtr;
IMPORT struct Window*      MainWindowPtr;

MODULE void updatebattgadgets(void);
MODULE void drawbit(ULONG bit, UBYTE colour);
MODULE void readbatt(ABOOL print);
MODULE void writebatt(void);

AGLOBAL void batt1(void)
{   navigate();

    /* revert */
    setgadget(48, 98, 130, 12, "_Revert", NULL);
    BU91_Revert = PrevGadPtr = (struct Gadget *) CreateGadget
    (   BUTTON_KIND,
        PrevGadPtr,
        &Gadget,
        GT_Underscore, '_',
        TAG_DONE
    );

    /* write */
    setgadget(184, 98, 130, 12, "_Write", NULL);
    BU91_Write = PrevGadPtr = (struct Gadget *) CreateGadget
    (   BUTTON_KIND,
        PrevGadPtr,
        &Gadget,
        GT_Underscore, '_',
        TAG_DONE
    );

    readbatt(FALSE);
    // significant bits
    setgadget(360, 24, 0, 0, "AMIGA_AMNESIA ($00)", PLACETEXT_RIGHT);
    CB91_AmigaAmnesia = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GTCB_Checked, BattBuffer[0] & 1,
        TAG_DONE
    );
    setgadget(360, 38, 0, 0, "SHARED_AMNESIA ($40)", PLACETEXT_RIGHT);
    CB91_SharedAmnesia = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GTCB_Checked, BattBuffer[8] & 1,
        TAG_DONE
    );
    setgadget(360, 52, 0, 0, "SCSI_TIMEOUT ($01)", PLACETEXT_RIGHT);
    CB91_SCSITimeout = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GTCB_Checked, BattBuffer[0] & 2,
        TAG_DONE
    );
    setgadget(360, 66, 0, 0, "SCSI_LUNS ($02)", PLACETEXT_RIGHT);
    CB91_SCSILUNS = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GTCB_Checked, BattBuffer[0] & 4,
        TAG_DONE
    );
    setgadget(334, 80, 52, 12, "SCSI_HOST_ID ($41-43)", PLACETEXT_RIGHT);
    hostid = 0;
    if (!(BattBuffer[8] & 2))
        hostid += 4;
    if (!(BattBuffer[8] & 4))
        hostid += 2;
    if (!(BattBuffer[8] & 8))
        hostid++;
    oldhostid = hostid;
    IN91_SCSIHostID = PrevGadPtr = (struct Gadget *) CreateGadget
    (   INTEGER_KIND,
        PrevGadPtr,
        &Gadget,
        GTIN_Number, hostid,
        GA_TabCycle, TRUE,
        TAG_DONE
    );
    setgadget(360, 94, 0, 0, "SCSI_SYNC_XFER ($44)", PLACETEXT_RIGHT);
    CB91_SCSISyncXfer = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GTCB_Checked, BattBuffer[8] & 8,
        TAG_DONE
    );
    setgadget(360, 108, 0, 0, "SCSI_FASTSYNC ($45)", PLACETEXT_RIGHT);
    CB91_SCSIFastSync = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GTCB_Checked, BattBuffer[8] & 16,
        TAG_DONE
    );
    setgadget(360, 122, 0, 0, "SCSI_TAG_QUEUES ($46)", PLACETEXT_RIGHT);
    CB91_SCSITagQueues = PrevGadPtr = (struct Gadget *) CreateGadget
    (   CHECKBOX_KIND,
        PrevGadPtr,
        &Gadget,
        GTCB_Checked, BattBuffer[8] & 32,
        TAG_DONE
    );

    newwindow
    (   640, BATT1HEIGHT,
        "Report+: Battery-backed Memory",
        BUTTONIDCMP
    );

    DrawBevelBox(MainWindowPtr->RPort, BOXLEFTX, BOXTOPY, BOXRIGHTX - BOXLEFTX, BOXBOTTOMY - BOXTOPY, GT_VisualInfo, VisualInfoPtr, GTBB_Recessed, FALSE, TAG_DONE);
    SetAPen(MainWindowPtr->RPort, BLACK);
    Move(MainWindowPtr->RPort, 16, BOXTOPY + 10);
    Text(MainWindowPtr->RPort, "$00:", 4);
    Move(MainWindowPtr->RPort, 16, BOXTOPY + 18);
    Text(MainWindowPtr->RPort, "$20:", 4);
    Move(MainWindowPtr->RPort, 16, BOXTOPY + 26);
    Text(MainWindowPtr->RPort, "$40:", 4);
    Move(MainWindowPtr->RPort, 16, BOXTOPY + 34);
    Text(MainWindowPtr->RPort, "$60:", 4);
    Move(MainWindowPtr->RPort, 16, BOXTOPY + 42);
    Text(MainWindowPtr->RPort, "$80:", 4);
    Move(MainWindowPtr->RPort, 16, BOXTOPY + 50);
    Text(MainWindowPtr->RPort, "$A0:", 4);
    Move(MainWindowPtr->RPort, 16, BOXTOPY + 58);
    Text(MainWindowPtr->RPort, "$C0:", 4);
    Move(MainWindowPtr->RPort, 16, BOXTOPY + 66);
    Text(MainWindowPtr->RPort, "$E0:", 4);

    readbatt(TRUE);

    ActivateGadget(IN91_SCSIHostID, MainWindowPtr, NULL);
    loop();
    closewindow();
}

MODULE void updatebattgadgets(void)
{   GT_SetGadgetAttrs(CB91_AmigaAmnesia, MainWindowPtr, NULL,
                      GTCB_Checked, BattBuffer[0] & 1,
                      TAG_DONE);
    GT_SetGadgetAttrs(CB91_SharedAmnesia, MainWindowPtr, NULL,
                      GTCB_Checked, BattBuffer[8] & 1,
                      TAG_DONE);

    GT_SetGadgetAttrs(CB91_SCSITimeout, MainWindowPtr, NULL,
                      GTCB_Checked, BattBuffer[0] & 2,
                      TAG_DONE);
    GT_SetGadgetAttrs(CB91_SCSILUNS, MainWindowPtr, NULL,
                      GTCB_Checked, BattBuffer[0] & 4,
                      TAG_DONE);
    hostid = 0;
    if (!(BattBuffer[8] & 2))
        hostid += 4;
    if (!(BattBuffer[8] & 4))
        hostid += 2;
    if (!(BattBuffer[8] & 8))
        hostid++;
    oldhostid = hostid;
    GT_SetGadgetAttrs(IN91_SCSIHostID, MainWindowPtr, NULL,
                      GTIN_Number, hostid,
                      TAG_DONE);
    GT_SetGadgetAttrs(CB91_SCSISyncXfer, MainWindowPtr, NULL,
                      GTCB_Checked, BattBuffer[8] & 16,
                      TAG_DONE);
    GT_SetGadgetAttrs(CB91_SCSIFastSync, MainWindowPtr, NULL,
                      GTCB_Checked, BattBuffer[8] & 32,
                      TAG_DONE);
    GT_SetGadgetAttrs(CB91_SCSITagQueues, MainWindowPtr, NULL,
                      GTCB_Checked, BattBuffer[8] & 64,
                      TAG_DONE);
}

MODULE void drawbit(ULONG bit, UBYTE colour)
{   Move(MainWindowPtr->RPort, BOXLEFTX + 4 + (8 * (bit % 32)), BOXTOPY + 10 + (8 * (bit / 32)));
    SetAPen(MainWindowPtr->RPort, colour);
    if ((BattBuffer[bit / 8]) & (1 << (bit % 8)))
        Text(MainWindowPtr->RPort, "#", 1);
    else Text(MainWindowPtr->RPort, "-", 1);
}

MODULE void readbatt(ABOOL print)
{   ULONG i;

    ObtainBattSemaphore();
    if (ReadBattMem(&BattBuffer, 0, 256))
        rq("Can't read battery-backed memory!");
    if (print)
        for (i = 0; i <= 255; i++)
            drawbit(i, BLACK);
    ReleaseBattSemaphore();
}

AGLOBAL void batt_loop(ULONG class, struct Gadget* addr, UWORD code, UWORD qual, SWORD mousex, SWORD mousey)
{   // page is ALWAYS 91 in this routine, so it is not checked for.

    UWORD realx, realy, bit;

    if (class == IDCMP_MOUSEBUTTONS)
    {   if (code == SELECTDOWN && !(qual & IEQUALIFIER_REPEAT))
        {   if (mousex >= BOXLEFTX && mousex <= BOXRIGHTX && mousey >= BOXTOPY && mousey <= BOXBOTTOMY)
            {   realx = (mousex - BOXLEFTX - 2) / 8;
                realy = (mousey - BOXTOPY - 4) / 8;
                if (realx < 0)
                    realx = 0;
                elif (realx > 31)
                    realx = 31;
                if (realy < 0)
                    realy = 0;
                elif (realy > 7)
                    realy = 7;
                // now flip it
                bit = (realy * 32) + realx;
                if ((BattBuffer[bit / 8]) & (1 << (bit % 8)))
                    BattBuffer[bit / 8] &= 255 - (1 << (bit % 8));
                else BattBuffer[bit / 8] |= (1 << (bit % 8));
                drawbit(bit, WHITE);
                updatebattgadgets();
    }   }   }
    elif (class == IDCMP_VANILLAKEY)
    {   code = toupper(code);
        if (code == 'R')
            readbatt(TRUE);
        elif (code == 'W')
            writebatt();
        elif (code == ESCAPE)
            page = 0;
    } elif (class == IDCMP_GADGETUP)
    {   if (addr == BU99_Right)
            page = 0;
        elif (addr == CB91_AmigaAmnesia)
        {   if (CB91_AmigaAmnesia->Flags & GFLG_SELECTED)
                BattBuffer[0] &= 255 - 1;
            else BattBuffer[0] |= 1;
            drawbit(0, WHITE);
        } elif (addr == CB91_SharedAmnesia)
        {   if (CB91_SharedAmnesia->Flags & GFLG_SELECTED)
                BattBuffer[8] &= 255 - 1;
            else BattBuffer[8] |= 1;
            drawbit(64, WHITE);
        } elif (addr == CB91_SCSITimeout)
        {   if (CB91_SCSITimeout->Flags & GFLG_SELECTED)
                BattBuffer[0] &= 255 - 2;
            else BattBuffer[0] |= 2;
            drawbit(1, WHITE);
        } elif (addr == CB91_SCSILUNS)
        {   if (CB91_SCSILUNS->Flags & GFLG_SELECTED)
                BattBuffer[0] &= 255 - 4;
            else BattBuffer[0] |= 4;
            drawbit(2, WHITE);
        } elif (addr == IN91_SCSIHostID)
        {   hostid = ((struct StringInfo *) IN91_SCSIHostID->SpecialInfo)->LongInt;
            if (hostid < 0 || hostid > 7)
                GT_SetGadgetAttrs
                (   IN91_SCSIHostID,
                    MainWindowPtr, NULL,
                    GTIN_Number, oldhostid,
                    TAG_DONE
                );
            else
            {   oldhostid = hostid;
                if (hostid & 4)
                    BattBuffer[8] &= 255 - 2; // then clear the '4' bit
                else BattBuffer[8] |= 2;
                drawbit(65, WHITE);
                if (hostid & 2)
                    BattBuffer[8] &= 255 - 4; // then clear the '2' bit
                else BattBuffer[8] |= 4;
                drawbit(66, WHITE);
                if (hostid & 1)
                    BattBuffer[8] &= 255 - 8; // then clear the '1' bit
                else BattBuffer[8] |= 8;
                drawbit(67, WHITE);
        }   }
        elif (addr == CB91_SCSISyncXfer)
        {   if (CB91_SCSISyncXfer->Flags & GFLG_SELECTED)
                BattBuffer[8] &= 255 - 16;
            else BattBuffer[8] |= 16;
            drawbit(68, WHITE);
        } elif (addr == CB91_SCSIFastSync)
        {   if (CB91_SCSIFastSync->Flags & GFLG_SELECTED)
                BattBuffer[8] &= 255 - 32;
            else BattBuffer[8] |= 32;
            drawbit(69, WHITE);
        } elif (addr == CB91_SCSITagQueues)
        {   if (CB91_SCSITagQueues->Flags & GFLG_SELECTED)
                BattBuffer[8] &= 255 - 64;
            else BattBuffer[8] |= 64;
            drawbit(70, WHITE);
        } elif (addr == BU91_Revert)
            readbatt(TRUE);
        elif (addr == BU91_Write)
        {   writebatt();
}   }   }

AGLOBAL void batt_init(void)
{   BattMemBase = OpenResource(BATTMEMNAME);
}

MODULE void writebatt(void)
{   ObtainBattSemaphore();
    if (WriteBattMem(&BattBuffer, 0, 256))
    {   ReleaseBattSemaphore();
        rq("Can't write battery-backed memory!");
    }
    ReleaseBattSemaphore();
    readbatt(TRUE);
}

