#include <stdio.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <intuition/cghooks.h>
#include <intuition/classes.h>
#include <intuition/gadgetclass.h>
#include <intuition/imageclass.h>
#include <intuition/icclass.h>
#include <clib/intuition_protos.h>
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#include "rkmmodel.h"

#define LR_WIDTH 16
#define UD_HEIGHT 11

extern Class *initRKMModClass(void);

struct IntuitionBase *IntuitionBase;
struct UtilityBase *UtilityBase;

void add_test_gadget(struct Window *,struct Screen *);
void delete_test_gadget(struct Window *,struct Gadget *);
void msg_loop(struct Window *);

int main(void)
{
  struct Screen *sc;
  struct Window *w;
  struct Gadget *g;
  
  if((IntuitionBase=(struct IntuitionBase *)\
      OpenLibrary("intuition.library",37))!=NULL)
    {
      if((UtilityBase=(struct UtilityBase *)\
	  OpenLibrary("utility.library",37))!=NULL)
	{
	  if((sc=LockPubScreen(NULL))!=NULL)
	    {
	      if((w=OpenWindowTags(NULL, \
				   WA_PubScreen, sc, \
				   WA_Width, 200, \
				   WA_Height, 200, \
				   WA_Title, "Gadget Test", \
				   WA_DragBar, TRUE,\
				   WA_DepthGadget, TRUE,\
				   WA_GimmeZeroZero, TRUE,\
				   WA_SmartRefresh, TRUE,\
				   WA_AutoAdjust, TRUE,\
				   WA_SizeGadget, TRUE,\
				   WA_SizeBBottom, TRUE,\
				   WA_SizeBRight, TRUE,\
				   WA_MinWidth,50,\
				   WA_MaxWidth,1008,\
				   WA_MinHeight,50,\
				   WA_MaxHeight,1024,\
				   WA_CloseGadget,TRUE,\
				   WA_IDCMP,IDCMP_IDCMPUPDATE|\
				   IDCMP_CLOSEWINDOW,\
				   TAG_END))!=NULL)
		{
		  add_test_gadget(w,sc);
		  msg_loop(w);
		  CloseWindow(w);
		}
	      else fprintf(stderr,"can't open window\n");
	      UnlockPubScreen(NULL,sc);
	    }
	  else fprintf(stderr,"can't lock standard public screen\n");
	  CloseLibrary((struct Library *)UtilityBase);
	}
      else fprintf(stderr,"can't open untility library version >=37\n");
      CloseLibrary((struct Library *)IntuitionBase);
    }
  else fprintf(stderr,"can't open intuition library version >=37\n");
}

void add_test_gadget(struct Window *w,struct Screen *s)
{
  struct Gadget *pg_h;
  struct Gadget *bg_h1;
  struct Gadget *bg_h2=NULL;
  
  struct Gadget *pg_v;
  struct Gadget *bg_v1=NULL;
  struct Gadget *bg_v2=NULL;
  
  struct Image *up;
  struct Image *down;
  struct Image *left;
  struct Image *right;
  int tbs=w->BorderTop;
  int rbs=w->BorderRight;
  int bbs=w->BorderBottom;
  int lbs=w->BorderLeft;
  Class *rkm;
  struct Object *my_rkm_model1;
  struct Object *icc_c2p_h;
  struct Object *my_rkm_model2;
  struct Object *icc_c2p_v;
  static struct TagItem id2u_map[]={GA_ID,RKMMOD_Up,TAG_DONE};
  static struct TagItem id2d_map[]={GA_ID,RKMMOD_Down,TAG_DONE};
  static struct TagItem c2p_map[]={RKMMOD_CurrVal,PGA_Top,TAG_DONE};
  static struct TagItem p2c_map[]={PGA_Top,RKMMOD_CurrVal,TAG_DONE};
  
  if((pg_h=(struct Gadget *)NewObject(NULL,"propgclass",\
				      GA_ID,1,\
				      GA_RelBottom,-bbs+2,\
				      GA_Left,lbs,\
				      GA_RelWidth,-lbs-rbs-2*LR_WIDTH-2,\
				      GA_Height,bbs-3,\
				      GA_BottomBorder,TRUE,\
				      GA_GZZGadget,TRUE,\
				      PGA_Freedom,FREEHORIZ,\
				      PGA_NewLook, TRUE,\
				      PGA_Top,0,\
				      PGA_Total,100,\
				      PGA_Visible,20,\
				      TAG_END))!=NULL)
    AddGadget(w,pg_h,-1);
  if((left=(struct Image *)NewObject(NULL,"sysiclass",
				     IA_Left,0,\
				     IA_Top,0,\
				     IA_Width,16,\
				     IA_Height,10,\
				     SYSIA_Which,LEFTIMAGE,\
				     SYSIA_Size,SYSISIZE_MEDRES,\
				     SYSIA_DrawInfo,GetScreenDrawInfo(s),\
				     TAG_END))!=NULL)
    {
      if((bg_h1=(struct Gadget *)NewObject(NULL,"buttongclass",\
					   GA_ID,2,\
					   GA_RelBottom,-bbs+1,\
					   GA_RelRight,-rbs-2*LR_WIDTH,\
					   GA_Width,16,\
					   GA_Height,10,\
					   GA_Image,left,\
					   GA_GZZGadget,TRUE,\
					   GA_BottomBorder,TRUE,\
					   TAG_END))!=NULL)              
	AddGadget(w,bg_h1,-1);
    }
  if((right=(struct Image *)NewObject(NULL,"sysiclass",
				      IA_Left,0,\
				      IA_Top,0,\
				      IA_Width,16,\
				      IA_Height,10,\
				      SYSIA_Which,RIGHTIMAGE,\
				      SYSIA_Size,SYSISIZE_MEDRES,\
				      SYSIA_DrawInfo,GetScreenDrawInfo(s),\
				      TAG_END))!=NULL)
    {
      if((bg_h2=(struct Gadget *)NewObject(NULL,"buttongclass",\
					   GA_ID,3,\
					   GA_RelBottom,-bbs+1,\
					   GA_RelRight,-rbs-LR_WIDTH,\
					   GA_Width,16,\
					   GA_Height,10,\
					   GA_Image,right,\
					   GA_GZZGadget,TRUE,\
					   GA_BottomBorder,TRUE,\
					   TAG_END))!=NULL)
	AddGadget(w,bg_h2,-1);
    }
  if((pg_v=(struct Gadget *)NewObject(NULL,"propgclass",\
				      GA_ID,4,\
				      GA_Top,tbs,\
				      GA_RelRight,-rbs+4,\
				      GA_Width,rbs-6,\
				      GA_RelHeight,-tbs-bbs-2*UD_HEIGHT-1,\
				      GA_RightBorder,TRUE,\
				      GA_GZZGadget,TRUE,\
				      PGA_Freedom,FREEVERT,\
				      PGA_NewLook, TRUE,\
				      PGA_Top,0,\
				      PGA_Total,100,\
				      PGA_Visible,20,\
				      TAG_END))!=NULL)
    AddGadget(w,pg_v,-1);
  if((up=(struct Image *)NewObject(NULL,"sysiclass",
				   IA_Left,0,\
				   IA_Top,0,\
				   IA_Width,18,\
				   IA_Height,11,\
				   SYSIA_Which,UPIMAGE,\
				   SYSIA_Size,SYSISIZE_MEDRES,\
				   SYSIA_DrawInfo,GetScreenDrawInfo(s),\
				   TAG_END))!=NULL)
    {
      if((bg_v1=(struct Gadget *)NewObject(NULL,"buttongclass",\
					   GA_ID,5,\
					   GA_RelBottom,-bbs-2*UD_HEIGHT+1,\
					   GA_RelRight,-rbs+1,\
					   GA_Width,18,\
					   GA_Height,11,\
					   GA_Image,up,\
					   GA_GZZGadget,TRUE,\
					   GA_RightBorder,TRUE,\
					   TAG_END))!=NULL)
	AddGadget(w,bg_v1,-1);
    }
  if((down=(struct Image *)NewObject(NULL,"sysiclass",
				     IA_Left,0,\
				     IA_Top,0,\
				     IA_Width,18,\
				     IA_Height,11,\
				     SYSIA_Which,DOWNIMAGE,\
				     SYSIA_Size,SYSISIZE_MEDRES,\
				     SYSIA_DrawInfo,GetScreenDrawInfo(s),\
				     TAG_END))!=NULL)
    {
      if((bg_v2=(struct Gadget *)NewObject(NULL,"buttongclass",\
					   GA_ID,6,\
					   GA_RelBottom,-bbs-UD_HEIGHT+1,\
					   GA_RelRight,-rbs+1,\
					   GA_Width,18,\
					   GA_Height,11,\
					   GA_Image,down,\
					   GA_GZZGadget,TRUE,\
					   GA_BottomBorder,TRUE,\
					   TAG_END))!=NULL)
	AddGadget(w,bg_v2,-1);
    }
  
  if((rkm=initRKMModClass())!=NULL)
    {
      if((my_rkm_model1=NewObject(rkm,NULL,\
				  RKMMOD_CurrVal,0,\
				  RKMMOD_Limit,100,\
				  RKMMOD_Id,0,\
				  ICA_TARGET,ICTARGET_IDCMP,\
				  TAG_END))!=NULL)
	{
	  if((icc_c2p_h=NewObjectA(NULL,"icclass",NULL))!=NULL)
	    {
	      SetGadgetAttrs(pg_h,w,NULL,\
			     ICA_TARGET,my_rkm_model1,\
			     ICA_MAP,p2c_map);
	      SetGadgetAttrs(bg_h1,w,NULL,\
			     ICA_TARGET,my_rkm_model1,\
			     ICA_MAP,id2d_map);
	      SetGadgetAttrs(bg_h2,w,NULL,\
			     ICA_TARGET,my_rkm_model1,\
			     ICA_MAP,id2u_map);
	      DoMethod(my_rkm_model1,OM_ADDMEMBER,icc_c2p_h);
	      SetAttrs(icc_c2p_h,\
		       ICA_TARGET,pg_h,\
		       ICA_MAP,c2p_map);
	    }
	  else fprintf(stderr,"can't open icc object\n");
	}
      else fprintf(stderr,"can't open rkm model object\n");
      if((my_rkm_model2=NewObject(rkm,NULL,\
				  RKMMOD_CurrVal,0,\
				  RKMMOD_Limit,100,\
				  RKMMOD_Id,1,\
				  ICA_TARGET,ICTARGET_IDCMP,\
				  TAG_END))!=NULL)
	{
	  if((icc_c2p_v=NewObjectA(NULL,"icclass",NULL))!=NULL)
	    {
	      SetGadgetAttrs(pg_v,w,NULL,\
			     ICA_TARGET,my_rkm_model2,\
			     ICA_MAP,p2c_map);
	      SetGadgetAttrs(bg_v1,w,NULL,\
			     ICA_TARGET,my_rkm_model2,\
			     ICA_MAP,id2d_map);
	      SetGadgetAttrs(bg_v2,w,NULL,\
			     ICA_TARGET,my_rkm_model2,\
			     ICA_MAP,id2u_map);
	      DoMethod(my_rkm_model2,OM_ADDMEMBER,icc_c2p_v);
	      SetAttrs(icc_c2p_v,\
		       ICA_TARGET,pg_v,\
		       ICA_MAP,c2p_map);
	    }
	  else fprintf(stderr,"can't open icc object\n");
	}
      else fprintf(stderr,"can't open rkm model object\n");
    }
  else fprintf(stderr,"can't create rkm model class\n");
  RefreshGadgets(pg_h,w,NULL);
}

void delete_test_gadget(struct Window *w,struct Gadget *g)
{
}

void msg_loop(struct Window *w)
{
  struct IntuiMessage *imsg;
  BOOL end=FALSE;
  struct TagItem *ti,*tstate;
  BOOL is_rkmmod;
  ULONG val;
  int rkm_id;
  
  do
    {
      WaitPort(w->UserPort);
      while((imsg=(struct IntuiMessage *)GetMsg(w->UserPort))!=NULL)
	{
	  is_rkmmod=FALSE;
	  switch(imsg->Class)
	    {
	    case IDCMP_IDCMPUPDATE:
	      /*
	      fprintf(stderr,"curr val %d\n",imsg->Code);
	      */
	      tstate=ti=(struct TagItem *)imsg->IAddress;
	      while((ti=NextTagItem(&tstate))!=NULL)
		{
		  switch(ti->ti_Tag)
		    {
		    case RKMMOD_Id:
		      is_rkmmod=TRUE;
		      rkm_id=ti->ti_Data;
		      break;
		    case RKMMOD_CurrVal:
		      val=ti->ti_Data;
		      break;
		    }
		}
	      if(is_rkmmod)
		{
		  printf("rkmmod %d: %d\n",rkm_id,val);
		}
	      break;
	    case IDCMP_CLOSEWINDOW:
	      end=TRUE;
	      break;
	    }
	  ReplyMsg((struct Message *)imsg);
	}
    }
  while(!end);
}
