#include <stdlib.h>

#include <intuition/intuition.h>
#include <libraries/feelin.h>
#include <clib/utility_protos.h>
#include <clib/feelin_protos.h>

struct FeelinBase    *FeelinBase;
struct UtilityBase   *UtilityBase;

/// OBJ
struct LocalObjectData {
   BYTE           Mode;
   BYTE           Way;
};

#define FA_CrazyGauge_Mode    FCCA_BASE

long enum {
   FV_CrazyGauge_More,
   FV_CrazyGauge_Less,
   FV_CrazyGauge_TwoWays,
   FV_CrazyGauge_Crary
};
//+

///mNew
__saveds ULONG mNew(struct FeelinClass *cl, struct FeelinObject *obj,struct LocalObjectData *lod,ULONG *args)
{
   if (F_SuperDoA(cl,obj,FM_New,args))
   {
      lod->Mode = GetTagData(FA_CrazyGauge_Mode,FV_CrazyGauge_More,(struct TagItem *)args);
      lod->Way  = TRUE;

      return (ULONG) obj;
   }

   return NULL;
}
//+
///mHandleEvent
__saveds ULONG mHandleEvent(struct FeelinObject *obj,struct LocalObjectData *lod,struct FS_HandleEvent *he)
{
   ULONG val,max,min;

   if (he->Msg->Class == IDCMP_INTUITICKS)
   {
      F_Do(obj,FM_Get,
               FA_Numeric_Value,  &val,
               FA_Numeric_Max,    &max,
               FA_Numeric_Min,    &min, NULL);

      switch (lod->Mode)
      {
         case FV_CrazyGauge_More:
            F_Set(obj,FA_Numeric_Value,(val == max) ? min : (val + 1));
            break;
         case FV_CrazyGauge_Less:
            F_Set(obj,FA_Numeric_Value,(val == min) ? max : (val - 1));
            break;
         case FV_CrazyGauge_TwoWays:
            if (lod->Way)
            {
               if (val == max)
               {
                  lod->Way = FALSE;
               } else {
                  F_Set(obj,FA_Numeric_Value,val + 1);
               }
            }
            else
            {
               if (val == min)
               {
                  lod->Way = TRUE;
               } else {
                  F_Set(obj,FA_Numeric_Value,val - 1);
               }
            }
            break;
         case FV_CrazyGauge_Crary:
            srand(max);
            F_Set(obj,FA_Numeric_Value,(ULONG)rand());
            break;
      }

      return NULL;
   }
}
//+
///mDispatcher
__asm __saveds ULONG mDispatcher(
   register __a2 struct FeelinClass   *cl,
   register __a0 struct FeelinObject  *obj,
   register __d0 ULONG                 method,
   register __a1 ULONG                *args)
{
   struct LocalObjectData *lod = INST_DATA(cl,obj);

   switch (method)
   {
      case FM_New:         return mNew(cl,obj,lod,args);
      case FM_Show:               F_Do(obj,FM_ModifyHandler,IDCMP_INTUITICKS,NULL); return NULL;
      case FM_Hide:               F_Do(obj,FM_ModifyHandler,NULL,IDCMP_INTUITICKS); return NULL;
      case FM_HandleEvent: return mHandleEvent(obj,lod,(struct FS_HandleEvent *)args);
      default:             return F_SuperDoA(cl,obj,method,args);
   }
}
//+

///Main
void main()
{
   static struct FeelinClass *fcc;
   static APTR c,w, g,b;

   if (FeelinBase = (struct FeelinBase *)OpenLibrary("feelin.library",FV_VERSION))
   {
      UtilityBase = FeelinBase->Utility;

      if (fcc = F_CreateClass(FA_SuperID,     FC_Gauge,
                              FA_DataSize,    sizeof (struct LocalObjectData),
                              FA_Dispatcher,  mDispatcher,
                              NULL))
      {
         c = ClientObject,
            FA_Pen_Shine,     "c:FFDCA0",
            FA_Pen_Fill,      "c:AA7864",
            FA_Pen_Highlight, "c:2A1E19",

            Child, w = WindowObject, FA_Window_Title,"Feelin : Gauges",
               FA_Back, FI_Fill,

               Child, VGroup,
                  Child, g = HGroup,
                     Child, VGroup,
                        Child, Gauge(TRUE,0,100,25),
                        Child, Gauge(TRUE,0,100,50),
                        Child, Gauge(TRUE,0,100,75),
                        Child, Gauge(TRUE,0,100,100),
                        Child, F_NewObj(fcc->ID,FA_Horizontal,      TRUE,
                                                FA_Frame,           FP_Frame_Gauge,
                                                DontChain,
                                                FA_Numeric_Max,     100,
                                                FA_CrazyGauge_Mode, FV_CrazyGauge_Crary,
                                                NULL),
                     End,

                     Child, VBar,

                     Child, VGroup, FA_FixedHeight,TRUE,
                        Child, F_NewObj(fcc->ID,FA_Horizontal,      TRUE,
                                                FA_Frame,           FP_Frame_Gauge,
                                                DontChain,
                                                FA_Numeric_Max,     100,
                                                FA_Numeric_Value,   0,
                                                FA_CrazyGauge_Mode, FV_CrazyGauge_TwoWays,
                                                NULL),

                        Child, F_NewObj(fcc->ID,FA_Horizontal,      TRUE,
                                                FA_Frame,           FP_Frame_Gauge,
                                                DontChain,
                                                FA_Numeric_Max,     100,
                                                FA_Numeric_Value,   100,
                                                FA_CrazyGauge_Mode, FV_CrazyGauge_TwoWays,
                                                NULL),

                        Child, F_NewObj(fcc->ID,FA_Horizontal,      TRUE,
                                                FA_Frame,           FP_Frame_Gauge,
                                                DontChain,
                                                FA_Numeric_Max,     100,
                                                FA_Numeric_Value,   0,
                                                FA_CrazyGauge_Mode, FV_CrazyGauge_TwoWays,
                                                NULL),

                        Child, F_NewObj(fcc->ID,FA_Horizontal,      TRUE,
                                                FA_Frame,           FP_Frame_Gauge,
                                                DontChain,
                                                FA_Numeric_Max,     100,
                                                FA_Numeric_Value,   100,
                                                FA_CrazyGauge_Mode, FV_CrazyGauge_TwoWays,
                                                NULL),
                     End,
                  End,

                  Child, b = TextObject,
                     FA_InputMode,        FV_InputMode_Toggle,
                     FA_Fixed,            TRUE,
                     FA_Inner_Left,       6L,
                     FA_Inner_Right,      6L,
                     FA_Inner_Top,        3L,
                     FA_Inner_Bottom,     3L,
                     FA_Frame,            0x21,
                     FA_AltFrame,         0x00,
                     FA_Back,             FI_Fill,
                     FA_AltBack,          FI_Dark,
                     FA_Text,             "Toggle Gauges Look",
                     FA_Text_PreParse,    "`Ss`Sh`<0>",
                     FA_Text_AltPreParse, "`Sn`<1>",
                     FA_Text_VCenter,     TRUE,
                     End,
               End,

               FA_Window_ActiveObject, b,
            End,
         End;

         if (c)
         {
            F_Do(b,FM_Notify,FA_Selected,FV_Notify_Always,g,5,FM_Set,FA_Gauge_Simple,FV_Notify_Value,FA_Group_Forward,TRUE);
            F_Do(w,FM_Notify,FA_Window_CloseRequest,TRUE,FV_Notify_Client,2,FM_Client_ReturnID,FV_Client_Quit);
            F_Set(w,FA_Window_Open,TRUE);

            F_DoA(c,FM_Client_Run,NULL);

            F_DisposeObj(c);
         }
         F_RemoveClass(fcc);
      }
      CloseLibrary((struct Library *) FeelinBase);
   }
}
//+
