#include <exec/types.h>
#include <exec/libraries.h>
#include <exec/ports.h>
#include <intuition/intuition.h>
#include <libraries/gadtools.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "XCMD.h"
#include "XCMDTools.h"

#define forever for(;;)

/*
*     VARIABLES
*/
struct GadgetList *glist         = NULL;
struct Window     *window        = NULL;
struct Screen     *screen_lock   = NULL;
void              *vi            = NULL;
struct MsgPort    *port          = NULL;
BPTR              dir_lock;
struct Library    *GadToolsBase  = NULL;
struct TextAttr   Topaz80        = { "topaz.font",8,0,0 };
char              line[256];
struct Panel
  {
  BOOL pa_Set;
  char pa_Text[10];
  char pa_Command[256];
  };
struct Panel      Panel[25];
int               PanelIX = 0;


/*
*
*       PROTOS
*
*/

void Load(void);
void ParseLine(void);
BOOL InitPanel(void);


/*
*       void ParseLine(void)
*
*       Parse the line variable, and associate button name
*       and command to one of the gadget panel
*
*/
void ParseLine()
  {
  int i = 0;
  while((line[i] == ' ') && (line[i]))
    i++;
  if(line[i])
    {
    int j = 0;
    while((line[i] != ';') && (line[i]))
      {
      if(j<9)
        Panel[PanelIX].pa_Text[j] = line[i];
      else if(j==9)
        Panel[PanelIX].pa_Text[j] = '\0';
      i++;
      j++;
      }
    if((line[i] == ';') && (j<9))
      Panel[PanelIX].pa_Text[j] = '\0';
    if(line[i])
      {
      i++;
      while((line[i] == ' ') && (line[i]))
        i++;
      if(line[i])
        {
        int k = 0;
        while(line[i])
          {
          Panel[PanelIX].pa_Command[k] = line[i];
          i++; k++;
          }
        Panel[PanelIX].pa_Command[k] = line[i];
        Panel[PanelIX].pa_Set = TRUE;
        PanelIX++;
        }
      }
    }
  }




/*
*
*       void Load(void)
*
*       Load the file "panel.config" to define all gadgets
*       of the panel. Each read line is put in the variable
*       line and parse with ParseLine()
*
*/
void Load()
  {
  FILE *fp;
  int i,c;
  for(i = 0; i<25; i++)
    Panel[i].pa_Set = FALSE;
  fp = fopen("panel.config","r");
  if(fp)
    {
    forever         /* Read until EOF */
      {
      i = 0;
      forever
        {
        c = fgetc(fp);
        if((c == EOF) || (c == '\n') || (i == 255))
          {
          line[i] = '\0';
          break;
          }
        else
          {
          line[i] = c;
          i++;
          }
        }
      if(strlen(line) && (line[0] != '#'))
        ParseLine();
      if ((c == EOF) || (PanelIX == 25)) break;
      }
    fclose(fp);
    }
  }



/*
*       InitPanel()
*
*       The panel is initialized, informations
*       read from "panel.config", parsed, open
*       window and create gadgets. Retourne TRUE
*       if everything is OK, FALSE otherwise.
*
*/
BOOL InitPanel()
  {
  vi = GetVisualInfo(screen_lock, TAG_DONE);
  if(!vi)
    {
    puts("Unable to get visual info");
    return(FALSE);
    }
  window = OpenWindowTags(NULL,
    WA_DragBar, TRUE,
    WA_DepthGadget, TRUE,
    WA_PubScreen, screen_lock,
    WA_Width, 417,
    WA_Height, 90,
    WA_CloseGadget, TRUE,
    WA_IDCMP, CLOSEWINDOW|REFRESHWINDOW|BUTTONIDCMP,
    WA_Title, "Command panel",
    WA_Activate, TRUE,
    TAG_DONE);
  if(!window)
    {
    puts("Unable to open window");
    return(FALSE);
    }

  struct Gadget *gad = CreateContext(&glist);
  struct NewGadget ng;

  ng.ng_TextAttr = &Topaz80;
  ng.ng_VisualInfo = vi;
  ng.ng_LeftEdge = 5;
  ng.ng_TopEdge = 12;
  ng.ng_Width = 80;
  ng.ng_Height = 14;
  ng.ng_Flags = 0;
  ng.ng_GadgetText = NULL;

  for(int j=0; j<5; j++)
    {
    for(int i = 0; i<5; i++)
      {
      int k = j*5 + i;
      ng.ng_GadgetID = k;
      if(Panel[k].pa_Set)
        ng.ng_GadgetText = Panel[k].pa_Text;
      else
        ng.ng_GadgetText = NULL;
      gad = CreateGadget(BUTTON_KIND,gad,&ng,TAG_DONE);
      ng.ng_LeftEdge += 82;
      }
    ng.ng_TopEdge += 15;
    ng.ng_LeftEdge = 5;
    }

  if(!gad)
    {
    puts("Unable to create gadgets");
    return(FALSE);
    }

  AddGList(window,glist,-1,-1,NULL);
  RefreshGList(glist,window,NULL,-1);
  GT_RefreshWindow(window,NULL);
  return(TRUE);
  }




/*
*
*           main()
*
*
*/

int main()

  {
  /*
  *     Check we are not already running
  */
  if(FindPort("PANEL_PORT"))
    {
    puts("I am already here");
    exit(10);
    }
  /*
  *     Open gadget toolkit
  */
  GadToolsBase = OpenLibrary("gadtools.library",36);
  if(!GadToolsBase)
    {
    puts("Unable to open gadget toolkit");
    exit(10);
    }
  /*
  *     Create message port
  */
  port = CreatePort("PANEL_PORT",0);
  if(!port)
    {
    puts("Unable to open PANEL_PORT");
    CloseLibrary(GadToolsBase);
    exit(10);
    }
  /*
  *     Wait for a START command from Term II
  */
  forever
    {
    WaitPort(port);
    struct XCMD *xcmd = GetMsg(port);
    if(xcmd && (xcmd->xcmd_TermCmd == XCMD_START))
      {
      screen_lock = xcmd->xcmd_TermScreen;
      dir_lock    = xcmd->xcmd_TermDir;
      ReplyMsg(xcmd);
      break;
      }
    else
      ReplyMsg(xcmd);
    }
  /*
  *     Go in the same directory than Term II
  *     to read config file.
  */
  BPTR old_lock = CurrentDir(dir_lock);
  /*
  *     Read configuration file
  */
  Load();
  /*
  *     Create panel
  */
  struct XCMD *xcmd = CreateXCMD(port);
  if(InitPanel() && xcmd)
    {
    BOOL not_the_end = TRUE;
    struct IntuiMessage *msg;
    ULONG IntuiSignal = 1 << window->UserPort->mp_SigBit;
    ULONG XCMDSignal  = 1 << port->mp_SigBit;
    while(not_the_end)
      {
      ULONG signals = Wait(IntuiSignal|XCMDSignal);
      if(signals & IntuiSignal)
        {
        /*
        *       We have been signaled by Intuition
        */
        while(msg = GT_GetIMsg(window->UserPort))
          {
          ULONG class = msg->Class;
          SHORT code = msg->Code;
          struct Gadget *gadget = msg->IAddress;
          GT_ReplyIMsg(msg);
          switch(class)
            {
            case CLOSEWINDOW:
              not_the_end = FALSE;
              break;
            case REFRESHWINDOW:
              GT_BeginRefresh(window);
              GT_EndRefresh(window,TRUE);
              break;
            case GADGETUP:
              /*
              *     A gadget has been clicked
              */
              xcmd->xcmd_Command = Panel[gadget->GadgetID].pa_Command;
              if(SendXCMD(xcmd))
                {
                /*
                *   We _must_ wait for Term answer
                */
                WaitPort(port);
                GetMsg(port);
                }
              /*
              *     Command is done
              */
              break;
            }
          }
        }
      if(signals & XCMDSignal)
        {
        /*
        *       We receive a message from Term II.
        *       It can only be a START or a STOP
        *       command.
        */
        struct XCMD *x = GetMsg(port);
        if(x->xcmd_TermCmd == XCMD_STOP)
          not_the_end = FALSE;
        else
          {
          /*
          *     It is a START sent by mistake.
          *     We free the locks and return
          *     the message
          */
          UnLock(x->xcmd_TermDir);
          UnlockPubScreen(NULL,x->xcmd_TermScreen);
          }
        ReplyMsg(x);
        }
      }
    }
  if(xcmd)
    DeleteXCMD(xcmd);
  if(port)
    DeletePort(port);
  if(window)
    {
    struct IntuiMessage *msg;
    while(msg = GT_GetIMsg(window->UserPort)) GT_ReplyIMsg(msg);
    CloseWindow(window);
    };
  if(vi)
    FreeVisualInfo(vi);
  if(GadToolsBase)
    {
    FreeGadgets(glist);
    UnlockPubScreen(NULL,screen_lock);
    CloseLibrary(GadToolsBase);
    }
  CurrentDir(old_lock);
  UnLock(dir_lock);
  }
