/* Rain 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;

/* #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 RP_Drops DTAG(0)
#define RP_Colors DTAG(1)

#define DEF_COLORS 8L
#define MAX_COLORS 128L

#define DEF_DROPS 8L
#define MAX_DROPS 100L

#ifndef max
#define max( x, y ) ((x)>(y)?(x):(y))
#endif

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

struct BTDInteger RainIntParams[] =
 {
  RP_Drops,"Drops",BTDPT_INTEGER,DEF_DROPS,1L,MAX_DROPS,TRUE,
  RP_Colors,"Colors",BTDPT_INTEGER,DEF_COLORS,1L,MAX_COLORS,TRUE
 };

struct BTDNode *RainParams[] = 
 {
  &RainIntParams[0].BI_Node,
  &RainIntParams[1].BI_Node,
  NULL
 };

struct BTDInfo RainInfo =
 {
  BTDI_Revision,MAKE_ID('R','A','I','N'),
  "Rain Blanker","I love it's rain' again..","Markus Illenseer 1994",
  RainParams
 };

struct RainStruct
 {
  struct BTDDrawInfo *BTDDrawInfo;
  LONG Colors;
  LONG Drops;
  LONG DropCount;
  LONG RandN,RandF,RandI;
 };

/* library stuff */

char MyBlankerName[] = "rain.btd";
char MyBlankerID[]   = "Rainy 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 &RainInfo;
}

void __regargs InitRandom(struct RainStruct *RP,ULONG Instance)

{
 ULONG Time[2];

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

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

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

WORD __regargs Random(struct RainStruct *RP,WORD Max)

{
 RP->RandN=RP->RandF*RP->RandN+RP->RandI;
 if (RP->RandN<0L) RP->RandN=-RP->RandN;

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

struct RainStruct *InitMyBlanker(struct TagItem *TagList)

{
 struct RainStruct *RP;
 struct BTDDrawInfo *BTDDrawInfo;
 ULONG *Error,Dummy,Instance,Index,Step;

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

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

 InitRandom(RP,Instance);

 RP->Colors=FindTagData(TagList,RP_Colors,DEF_COLORS);
 RP->Drops=FindTagData(TagList,RP_Drops,DEF_DROPS);
 RP->DropCount=0L;

 Step=(MAX_COLORS/(RP->Colors));

 for(Index=0; Index<RP->Colors; Index++)
  {
   BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[Index]]=64+Step*Index;
   BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[Index]]=64+Step*Index;
   BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[Index]]=64+Step*Index;
   BTDDrawInfo->BDI_Changed[BTDDrawInfo->BDI_Pens[Index]]=TRUE;
  }

 return RP;
}

void EndMyBlanker(struct RainStruct *RP)

{
DEBUG_PRINT("Rain: FreeMem\n");
 FreeVec (RP);
}

void AnimMyBlanker(struct RainStruct *RP)

{

 LONG Rad,x,y,Step,Index;

  if(RP->DropCount++ >RP->Drops)
   {
    SetAPen (RP->BTDDrawInfo->BDI_RPort,BTD_BgPen);
    RectFill (RP->BTDDrawInfo->BDI_RPort,
              RP->BTDDrawInfo->BDI_Left,
              RP->BTDDrawInfo->BDI_Top,
              RP->BTDDrawInfo->BDI_Left+RP->BTDDrawInfo->BDI_Width-1,
              RP->BTDDrawInfo->BDI_Top+RP->BTDDrawInfo->BDI_Height-1);
    RP->DropCount=0L;
   }

   Rad = Random(RP, (RP->BTDDrawInfo->BDI_Width-1)/18)+(RP->BTDDrawInfo->BDI_Width-1)/35;
   x = Random(RP,(RP->BTDDrawInfo->BDI_Width-1)-2*Rad)+Rad+RP->BTDDrawInfo->BDI_Left;
   y = Random(RP,(RP->BTDDrawInfo->BDI_Height-1)-2*Rad)+Rad +RP->BTDDrawInfo->BDI_Top;
	
   Step=max( RP->BTDDrawInfo->BDI_Width/160, 1 );
   WaitTOF();
   for(Index=0; Index<Rad; Index += Step )
    {
      SetAPen(RP->BTDDrawInfo->BDI_RPort,RP->BTDDrawInfo->BDI_Pens[Random(RP,RP->Colors-1)]);
      DrawEllipse(RP->BTDDrawInfo->BDI_RPort,x,y,Index,Index);
      if(Index>0)
       {
        SetAPen (RP->BTDDrawInfo->BDI_RPort,BTD_BgPen);
        DrawEllipse(RP->BTDDrawInfo->BDI_RPort,x,y,Index-Step,Index-Step);
       }
    }
}

ULONG PenCountMyBlanker(struct TagItem *TagList)

{
 return FindTagData(TagList,RP_Colors,DEF_COLORS);;
}
