#include <exec/types.h>

#include <string.h>
#include <intuition/gadgetclass.h>
#include <math.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/gadtools.h>
#include <proto/intuition.h>
#include <proto/icon.h>
#include <proto/graphics.h>
#include <proto/wb.h>
#include <proto/commodities.h>
#include <proto/diskfont.h>
#include <proto/graphics.h>
#include <proto/utility.h>

#include "WBStartup+Prefs.h"
#include "WBStartupPlusPrefs_Cat.h"

struct Node *ChooseGroup(UWORD x, UWORD y, struct List *list, char *windowtitle);
struct Gadget *createChooseGroupGadgets(struct Gadget **glistptr, void *vi, struct Window *win, struct Gadget *my_gads[], struct List *list);


struct Node *ChooseGroup(UWORD x, UWORD y, struct List *list, char *windowtitle)
{
  /* WORD x         The current X mouse position */
  /* WORD y         The current Y mouse position */
  /* char *windowtitle  The title of the window */
  /* RETURNS a pointer to choosen node, or NULL if canceled */

  ULONG signals;
  ULONG winsigflag;
  BOOL LOOP;
  struct IntuiMessage *winmsg;
  struct Window *win;
  struct Screen *scr;
  struct VisualInfo *vi;
  ULONG winheight,winwidth;
  struct Gadget *glist=NULL, *my_gads[TOTALGADGETS];
  BOOL  success=TRUE;  /* FALSE if cancel was selected */
  struct Node *n = NULL;
  ULONG selectedline;
  ULONG oldsecs=0, oldmicros=0;
  ULONG oldselection=~0;

  if (IsListEmpty(list))
    return(NULL);

  if (scr=LockPubScreen(NULL))
  {
    if (vi=GetVisualInfo(scr,TAG_END))
    {

      winheight = BestWindowHeight(scr,list);
      winwidth  = (2 * TextLength(&scr->RastPort,windowtitle,strlen(windowtitle))) + 40; /* 40 is for the close and depth gadgets */
      if (win = OpenWindowTags(NULL,
          WA_Left,   x - (winwidth/2),
          WA_Top,    y - (winheight/2),
          WA_Width, winwidth,
          WA_Height, winheight,
          WA_MinWidth, 264,
          WA_MinHeight, scr->WBorTop + (2 * scr->Font->ta_YSize) + 1 + 160 + scr->WBorBottom,
          WA_MaxWidth, ~0,
          WA_MaxHeight, ~0,
          WA_AutoAdjust, TRUE,
          WA_IDCMP,  IDCMP_NEWSIZE | IDCMP_GADGETUP | IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | LISTVIEWIDCMP,
          WA_Flags,  WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_SMART_REFRESH | WFLG_ACTIVATE,
          WA_Title,  windowtitle,
          WA_PubScreen, scr,
          TAG_END))
      {
        winsigflag = 1L<<win->UserPort->mp_SigBit;

        if (RenderGadgets(&glist, vi, win, my_gads, list, createChooseGroupGadgets))
        {

          LOOP=TRUE;
          while (LOOP)
          {
            signals=Wait(SIGBREAKF_CTRL_C | winsigflag);

            if (signals & SIGBREAKF_CTRL_C)
              LOOP=FALSE;

            if (signals & winsigflag)
            {
              while (winmsg = (struct IntuiMessage *)GT_GetIMsg((struct MsgPort *)win->UserPort))
              {
                switch(winmsg->Class)
                {
                  case IDCMP_NEWSIZE:
                    RemoveGList(win,glist,-1);
                    FreeGadgets(glist);
                    RefreshWindowFrame(win);
                    RenderGadgets(&glist, vi, win, my_gads, list, createChooseGroupGadgets);
                    break;
                  case IDCMP_GADGETUP:
                    switch(((struct Gadget *)winmsg->IAddress)->GadgetID)
                    {
                      case SAVE_GAD:
                        LOOP=FALSE;
                        break;
                      case CANCEL_GAD:
                        success=FALSE;
                        LOOP=FALSE;
                        break;
                      case LIST_GAD:
                        if ((winmsg->Code == oldselection) && (DoubleClick(oldsecs, oldmicros, winmsg->Seconds, winmsg->Micros)))
                            LOOP= FALSE;
                          else
                          {
                            oldsecs = winmsg->Seconds;
                            oldmicros = winmsg->Micros;
                            oldselection = winmsg->Code;
                          }
                        break;
                    }
                    break;
                  case IDCMP_REFRESHWINDOW:
                    BeginRefresh(win);
                    EndRefresh(win, TRUE);
                    break;
                  case IDCMP_CLOSEWINDOW:
                    LOOP=FALSE;
                    break;
                }
                GT_ReplyIMsg(winmsg);
              }
            }  /* End of process window events */
          }   /* End of while (LOOP) */

          GT_GetGadgetAttrs(my_gads[LIST_GAD],win,NULL,GTLV_Selected, &selectedline);

          if ((selectedline == ((ULONG)~0)) || (!success))
            n=NULL;
          else
            for (n = list->lh_Head; selectedline; selectedline--)
              n = n->ln_Succ;

          RemoveGList(win,glist,-1);
        }
        FreeGadgets(glist);
        CloseWindow(win);
      }  /* End of if (OpenWindowTags()) */
      FreeVisualInfo(vi);
    }
    UnlockPubScreen(NULL,scr);
  }


  return(n);
}

struct Gadget *createChooseGroupGadgets(struct Gadget **glistptr, void *vi, struct Window *win, struct Gadget *my_gads[], struct List *list)
{
  struct NewGadget ng;
  struct Gadget *gad;
  ULONG  buttonwidth,maxbuttonwidth;
  ULONG  oktextwidth,canceltextwidth;
  #define OUTSIDEBORDER 10
  #define GADTEXTBORDERSUM 6

  gad = CreateContext(glistptr);

  ng.ng_LeftEdge = win->BorderLeft+OUTSIDEBORDER;
  ng.ng_TopEdge = win->BorderTop+OUTSIDEBORDER;
  ng.ng_Width = win->Width - win->BorderRight-win->BorderLeft-(2 * OUTSIDEBORDER);
  ng.ng_Height = win->Height-win->BorderTop-OUTSIDEBORDER-8-win->WScreen->Font->ta_YSize - GADTEXTBORDERSUM - 4 - win->BorderBottom;
  ng.ng_GadgetText = NULL;
  ng.ng_TextAttr = win->WScreen->Font;
  ng.ng_VisualInfo = vi;
  ng.ng_GadgetID = LIST_GAD;
  ng.ng_Flags = 0;

  my_gads[LIST_GAD] = gad = CreateGadget(LISTVIEW_KIND,gad,&ng,
      GTLV_Labels,list,
      GTLV_ShowSelected,0,
      LAYOUTA_Spacing,2,
      TAG_DONE);

  /* Determine the optimal width of the Ok and Cancel gadgets */
  canceltextwidth = TextLength(&win->WScreen->RastPort,GetString(STRCancel),strlen(GetString(STRCancel)));
  oktextwidth   = TextLength(&win->WScreen->RastPort,GetString(STROk),strlen(GetString(STROk)));
  maxbuttonwidth = 2 * max(canceltextwidth,oktextwidth);
  buttonwidth = min(maxbuttonwidth , ((win->Width - win->BorderLeft - win->BorderRight- (OUTSIDEBORDER*2))/2)-8);

  ng.ng_TopEdge = win->Height - (win->WScreen->Font->ta_YSize + GADTEXTBORDERSUM + 4 + win->BorderBottom);
  ng.ng_Width = buttonwidth;
  ng.ng_Height = win->WScreen->Font->ta_YSize + GADTEXTBORDERSUM;
  ng.ng_GadgetText = GetString(STROk);
  ng.ng_GadgetID = SAVE_GAD;

  my_gads[SAVE_GAD] = gad = CreateGadget(BUTTON_KIND,gad,&ng,TAG_DONE);

  ng.ng_LeftEdge = win->Width-win->BorderRight - OUTSIDEBORDER-buttonwidth;
  ng.ng_GadgetText = GetString(STRCancel);
  ng.ng_GadgetID = CANCEL_GAD;

  my_gads[CANCEL_GAD] = gad = CreateGadget(BUTTON_KIND,gad,&ng,TAG_DONE);

  return(gad);
}

