/* Darkness Library */

#include <exec/memory.h>
#include <exec/execbase.h>
#include <graphics/gfxbase.h>
#include <intuition/intuitionbase.h>
#include <libraries/iffparse.h>
#include <utility/tagitem.h>

#include <clib/macros.h>

#define __USE_SYSBASE 42

#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/utility.h>

#include <BTD.h>

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *UtilityBase;


/* #define DEBUG YES */

#ifdef DEBUG 

void KPrintF(char *,...);

#define DEBUG_PRINTF(a,b)  KPrintF(a,b);
#define DEBUG_PRINT(a)     KPrintF(a)
#else
#define DEBUG_PRINTF(a,b)
#define DEBUG_PRINT(a)
#endif

#define DTAG(o) (BTD_Client+(o))

#define DP_Mode    DTAG(0)
#define DP_Seconds DTAG(1)

#define DEF_SECONDS 60L
#define MAX_SECONDS 3600L

#define DEF_MODES 0L
#define MAX_MODES 1L

char *Modes[] = {"Stay Dark","Cycle once in a while",NULL};

struct BTDCycle DarkCycleParams[] =
 {
  DP_Mode,"Mode",BTDPT_CYCLE,DEF_MODES,Modes
 };

struct BTDInteger DarkIntParams[] =
 {
  DP_Seconds,"Seconds",BTDPT_INTEGER,DEF_SECONDS,1L,MAX_SECONDS,TRUE,
 };

struct BTDNode *DarkParams[] = 
 {
  &DarkCycleParams[0].BC_Node,
  &DarkIntParams[0].BI_Node,
  NULL
 };

struct BTDInfo DarknessInfo =
 {
  BTDI_Revision,MAKE_ID('D','A','R','K'),
  "Darkness Blanker","Total Darkness","Markus Illenseer 1994",
  DarkParams
 };

struct DarkStruct
 {
  struct BTDDrawInfo *BTDDrawInfo;
  LONG Seconds;
  LONG Mode;
  LONG Time;
  LONG RandN,RandF,RandI;
 };

/* library stuff */

char MyBlankerName[] = "darkness.btd";
char MyBlankerID[]   = "Darkness Blanker V" VERSION "." REVISION " for BTD";


LONG MyBlankerLibInit(void)

{
 if (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L))
  {
   if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L))
    {
     if (UtilityBase=OpenLibrary("utility.library",37L)) return TRUE;

     CloseLibrary (&IntuitionBase->LibNode);
    }
   CloseLibrary (&GfxBase->LibNode);
  }
 return FALSE;
}

void MyBlankerLibFree(void)

{
 CloseLibrary (UtilityBase);
 CloseLibrary (&IntuitionBase->LibNode);
 CloseLibrary (&GfxBase->LibNode);
}

struct BTDInfo *QueryMyBlanker(void)
{
 return &DarknessInfo;
}

void __regargs InitRandom(struct DarkStruct *DP,ULONG Instance)

{
 ULONG Time[2];

 CurrentTime (&Time[0],&Time[1]);
 DP->RandN=(LONG)Time[0];

 if (Time[1]<1024L) Time[1]|=1;
 else Time[1]>>=10;
 Time[1]^=Instance;

 DP->RandF=4*Time[1]+1;
 DP->RandI=2*Time[1]+1;
}

WORD __regargs Random(struct DarkStruct *DP,WORD Max)
{
 DP->RandN=DP->RandF*DP->RandN+DP->RandI;
 if (DP->RandN<0L) DP->RandN=-DP->RandN;

 return (WORD)(DP->RandN%Max);
}

#define FindTagData(l,t,d) GetTagData((t),(d),(l))

struct DarkStruct *InitMyBlanker(struct TagItem *TagList)

{
 struct DarkStruct *DP;
 struct BTDDrawInfo *BTDDrawInfo;
 ULONG *Error,Dummy,Instance;

 if ((BTDDrawInfo=(struct BTDDrawInfo *)
                   FindTagData(TagList,BTD_DrawInfo,NULL))==NULL) return NULL;
 Error=(LONG *)FindTagData(TagList,BTD_Error,(ULONG)&Dummy);
 if ((DP=AllocVec(sizeof(struct DarkStruct),MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  {
   *Error=BTDERR_Memory;
   return NULL;
  }

 DP->BTDDrawInfo=BTDDrawInfo;
 Instance=FindTagData(TagList,BTD_Instance,0L);

 InitRandom(DP,Instance);

 DP->Seconds=FindTagData(TagList,DP_Seconds,DEF_SECONDS);
 DP->Mode=FindTagData(TagList,DP_Mode,DEF_MODES);

 if(DP->Mode==1L) 
  {
   BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[0]]=0;
   BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[0]]=0;
   BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[0]]=0;
   BTDDrawInfo->BDI_Changed[BTDDrawInfo->BDI_Pens[0]]=TRUE;
   SetAPen (BTDDrawInfo->BDI_RPort,BTDDrawInfo->BDI_Pens[0]);
   RectFill(BTDDrawInfo->BDI_RPort,BTDDrawInfo->BDI_Left,
                                   BTDDrawInfo->BDI_Top,
                                   BTDDrawInfo->BDI_Left+BTDDrawInfo->BDI_Width-1,
                                   BTDDrawInfo->BDI_Top+BTDDrawInfo->BDI_Height-1);
  }


 DP->Time=Random(DP,60);

 return DP;
}

void EndMyBlanker(struct DarkStruct *DP)

{
DEBUG_PRINT("Dark: FreeMem\n");
 FreeVec (DP);
}

void AnimMyBlanker(struct DarkStruct *DP)

{
 ULONG Seconds,Micros;

 CurrentTime (&Seconds,&Micros);

 if(DP->Mode==0L) WaitTOF();
 else
  if (Seconds>=DP->Time)
  {
   WaitTOF();
   DP->Time=Seconds+DP->Seconds;
   DP->BTDDrawInfo->BDI_Red[DP->BTDDrawInfo->BDI_Pens[0]]=Random(DP,255);
   DP->BTDDrawInfo->BDI_Green[DP->BTDDrawInfo->BDI_Pens[0]]=Random(DP,255);
   DP->BTDDrawInfo->BDI_Blue[DP->BTDDrawInfo->BDI_Pens[0]]=Random(DP,255);
   DP->BTDDrawInfo->BDI_Changed[DP->BTDDrawInfo->BDI_Pens[0]]=TRUE;
  }

}

ULONG PenCountMyBlanker(struct TagItem *TagList)

{
 return ((FindTagData(TagList,DP_Mode,DEF_MODES)==1)?(ULONG)1:(ULONG)0L);
}
