#include "version.h"
#include <stdio.h>
#include "pre.h"
#include "StarLex.h"
#include "structs.h"
#include <exec/lists.h>

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *GadToolsBase;
struct Library *AslBase;

struct List list;
char tmparray[80];
char textarray[50];
char commenttext[50];
char ynum[4], xnum[4];
void *Universe[61][61][9]=NULL;
struct { 
 int x, y;
} coord[9];
USHORT Colormap[]=
{ 
  0x9aa, 
  0x000, 
  0xFFF, 
  0x566, 
  0xF00, /* Red */
  0x0F0, /* Green */
  0x00F, /* Blue */
  0xFF0, /* Yellow */              
  0x0FF, /* Cyan */
  0xF0F  /* Magenta */
};

FILE *file;
int x, y, z;
int X=0, Y=0, Z=0;
int tmp;

int openlibs()
{
  if (GfxBase = (struct GfxBase *)OpenLibrary((UBYTE*)"graphics.library", 0)) 
  {
    if (IntuitionBase = (struct IntuitionBase *)OpenLibrary((UBYTE*)"intuition.library", 0))
    {
      if (GadToolsBase = OpenLibrary((UBYTE*)"gadtools.library", 37))
      {
        if (AslBase=OpenLibrary((UBYTE *)AslName, 38L))
        {
          return 1;
        }
        else
        {
          printf("Cannot open asl.library Version 38.\n");
          return 0;
        }
      }
      else
      {
        printf("Cannot open gadtools.library.\n");
        return 0;
      }
    }
    else
    {
      printf("Cannot open intuition.library!!!!????\n");
      return 0;
    }
  }
  else
  {
    printf("Cannot open graphics.library!!!!????\n");
    return 0;
  }
}

closelibs()
{
  if (AslBase) CloseLibrary(AslBase);
  if (GadToolsBase) CloseLibrary(GadToolsBase);
  if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
  if (GfxBase) CloseLibrary((struct Library *)GfxBase);
}

StringRequest(char *retval)
{
  struct IntuiMessage *im;
  short notDone = 1;
 
  StrReqLeft=(StarLexWnd->Width-StrReqWidth)/2;
  StrReqTop=(StarLexWnd->Height-StrReqHeight)/2;
  OpenStrReqWindow();
  
  while (notDone) {
    ActivateGadget(StrReqGadgets[GDX_TEXT], StrReqWnd, NULL);
    WaitPort(StrReqWnd->UserPort);
    while (im = GT_GetIMsg(StrReqWnd->UserPort)) {
      switch(im->Class) {
        case IDCMP_REFRESHWINDOW:
          GT_BeginRefresh(StarLexWnd);
          GT_EndRefresh(StarLexWnd, TRUE);
          break;
        case IDCMP_GADGETUP:
          switch(((struct Gadget *)im->IAddress)->GadgetID) 
          {
          case GD_TEXT:
            strcpy(retval, 
                 (char *)((struct StringInfo *)(StrReqGadgets[GDX_TEXT]->SpecialInfo))->Buffer);
            notDone=0;
            break;
          default:
            break;
          }
          break;
        default:
	  break;
      }
      GT_ReplyIMsg(im);
    }
  }
  CloseStrReqWindow();
}

ClearList(struct List *list)
{
  while(RemHead(list));
}

AddList(struct List *list, char *s) 
{
  int ok=0;
  
  ok=strlen(s);
  while (ok>0)
  {
    struct Node *np = (struct Node *)calloc(1,sizeof(struct Node));

    np->ln_Pri = 0;
    np->ln_Name = (APTR)calloc(1,35);
    strncpy(np->ln_Name, s, 34);
    AddTail(list, np);
    ok-=34;
    s+=34;
  } 
}

ClearMap()
{
  SetAPen(StarLexWnd->RPort, 0);
  RectFill( StarLexWnd->RPort, 20, 32, 310, 177);

  DrawMyBorders(StarLexWnd->RPort);
}

showmap(int x, int y)
{
  int i, j, k;
  
  for (i=x-2; i<=x+2; i++)
    for (j=y-2; j<=y+2; j++)
      for (k=-4; k<=4; k++)
        if (Universe[30+i][30+j][4+k]!=NULL)        
        {
          Move(StarLexWnd->RPort, 161+(i-x)*60+coord[4+k].x, 107-(j-y)*30+coord[4+k].y);
          if (((struct System *)Universe[30+i][30+j][4+k])->type=='*')
          {
            SetAPen(StarLexWnd->RPort, 7);
            Text(StarLexWnd->RPort, (UBYTE *)"*", 1);
            SetAPen(StarLexWnd->RPort, 1);
          }
          else
          {
            SetAPen(StarLexWnd->RPort, 1);
            Text(StarLexWnd->RPort, (UBYTE *)"·", 1);
          }
          if (((struct System *)Universe[30+i][30+j][4+k])->Special=='!')
          {
            SetAPen(StarLexWnd->RPort, 4);
            SetDrMd(StarLexWnd->RPort, JAM1);
            Move(StarLexWnd->RPort, 161+(i-x)*60+coord[4+k].x, 107-(j-y)*30+coord[4+k].y);
            Text(StarLexWnd->RPort, (UBYTE *)"!", 1);
            SetDrMd(StarLexWnd->RPort, JAM2);
            SetAPen(StarLexWnd->RPort, 1);
          }
        }        
}

InitCoords()
{
  coord[0].x=-20;
  coord[0].y=-10;
  coord[1].x=0;
  coord[1].y=-10;
  coord[2].x=20;
  coord[2].y=-10;
  coord[3].x=-20;
  coord[3].y=0;
  coord[4].x=0;
  coord[4].y=0;
  coord[5].x=20;
  coord[5].y=0;
  coord[6].x=-20;
  coord[6].y=10;
  coord[7].x=0;
  coord[7].y=10;
  coord[8].x=20;
  coord[8].y=10;
}

main()
{
  struct IntuiMessage *im;
  short notDone = 1;
  USHORT selection, flags;
  ULONG menuNum, itemNum, subNum;
  int i, j, k;
  int mode=0; /* 0=Add Sector 1=Del Sector (System, Fleet) */

  if(!openlibs()) _abort();

  LoadStars(FALSE);

  InitCoords();

  SetupScreen();
  
  LoadRGB4(&(Scr->ViewPort), Colormap, 10);

  OpenStarLexWindow();
  StarLexRender();
  
  DrawMyBorders(StarLexWnd->RPort);

  showmap(0,0);

  NewList(&list);

  GT_RefreshWindow(StarLexWnd, NULL);
  while (notDone) {
    WaitPort(StarLexWnd->UserPort);
    while (im = GT_GetIMsg(StarLexWnd->UserPort)) {
      switch(im->Class) {
        case IDCMP_REFRESHWINDOW:
          GT_BeginRefresh(StarLexWnd);
          StarLexRender();
          showmap(X, Y);
          GT_EndRefresh(StarLexWnd, TRUE);
          break;
        case IDCMP_MOUSEBUTTONS:
          if (im->Code!=SELECTUP) break;
          if ((StarLexWnd->MouseX>20)
              &&(StarLexWnd->MouseX<315)
              &&(StarLexWnd->MouseY>30)
              &&(StarLexWnd->MouseY<180))
          {
            switch (mode)
            {
              case 0:
                if (Universe[30+x+X][30+y+Y][4+z]==NULL)
                {
                  Universe[30+x+X][30+y+Y][4+z]=(void *)calloc(1,sizeof(struct System));
                  ((struct System *)Universe[30+x+X][30+y+Y][4+z])->type='.';
                }
                showmap(X,Y);
                break;
              case 1:
                if ((Universe[30+x+X][30+y+Y][4+z]!=NULL)&&(((struct System *)Universe[30+x+X][30+y+Y][4+z])->type=='.')) 
                {
                  free(Universe[30+x+X][30+y+Y][4+z]);
                  Universe[30+x+X][30+y+Y][4+z]=NULL;
                }
                ClearMap();
                showmap(X,Y);
                break;
              case 2:
                if (Universe[30+x+X][30+y+Y][4+z]==NULL)
                {
                  Universe[30+x+X][30+y+Y][4+z]=(void *)calloc(1,sizeof(struct System));
                  ((struct System *)Universe[30+x+X][30+y+Y][4+z])->type='.';
                  ((struct System *)Universe[30+x+X][30+y+Y][4+z])->Special='!';
                }
                else
                  ((struct System *)Universe[30+x+X][30+y+Y][4+z])->Special='!';
                showmap(X,Y);
                break;
              case 3:
                if ((Universe[30+x+X][30+y+Y][4+z]!=NULL)&&(((struct System *)Universe[30+x+X][30+y+Y][4+z])->Special=='!')) 
                {
                  ((struct System *)Universe[30+x+X][30+y+Y][4+z])->Special='x';
                }
                ClearMap();
                showmap(X,Y);
                break;
              case 4: /* Add System */
                if (Universe[30+x+X][30+y+Y][4+z]==NULL)
                {
                  StringRequest(tmparray);
                  if (tmparray[0]!=' ') {
                    Universe[30+x+X][30+y+Y][4+z]=(void *)calloc(1,sizeof(struct System));
                    ((struct System *)Universe[30+x+X][30+y+Y][4+z])->type='*';
                    ((struct System *)Universe[30+x+X][30+y+Y][4+z])->SysName=(char *)calloc(1,strlen(tmparray)+1);
                    strcpy(((struct System *)Universe[30+x+X][30+y+Y][4+z])->SysName, tmparray);
                  }
                }
                showmap(X,Y);
                break;
              case 5: /* Remove System */
                if ((Universe[30+x+X][30+y+Y][4+z]!=NULL)&&(((struct System *)Universe[30+x+X][30+y+Y][4+z])->type=='*')) 
                {
                  free(((struct System *)Universe[30+x+X][30+y+Y][4+z])->SysName);
                  free(Universe[30+x+X][30+y+Y][4+z]);
                  Universe[30+x+X][30+y+Y][4+z]=NULL;
                }
                ClearMap();
                showmap(X,Y);
                break;
              case 6: /* Add Comment */
                if (Universe[30+x+X][30+y+Y][4+z]!=NULL)
                {
                  StringRequest(tmparray);
                  if (tmparray[0]!=' ') {
                    if (((struct System *)Universe[30+x+X][30+y+Y][4+z])->Comment)
                      free(((struct System *)Universe[30+x+X][30+y+Y][4+z])->Comment);
                    ((struct System *)Universe[30+x+X][30+y+Y][4+z])->Comment=(char *)calloc(1,strlen(tmparray)+1);
                    strcpy(((struct System *)Universe[30+x+X][30+y+Y][4+z])->Comment, tmparray);
                  }
                }
                break;
              case 7: /* Remove Comment */
                if ((Universe[30+x+X][30+y+Y][4+z]!=NULL)&&(((struct System *)Universe[30+x+X][30+y+Y][4+z])->Comment!=NULL)) 
                {
                  free(((struct System *)Universe[30+x+X][30+y+Y][4+z])->Comment);
                  ((struct System *)Universe[30+x+X][30+y+Y][4+z])->Comment=NULL;
                }
                break;
              default: break;
            }
          }
          break;
        case IDCMP_MOUSEMOVE:
          switch(((struct Gadget *)im->IAddress)->GadgetID)
          {
            case GD_XAXIS:
              sprintf(xnum, "%4d", X=im->Code-28);
              GT_SetGadgetAttrs(StarLexGadgets[GDX_X], StarLexWnd, NULL, GTTX_Text, xnum, TAG_END);
              ClearMap();
              showmap(X,Y);
              break;
            case GD_YAXIS: 
              sprintf(ynum, "%4d", Y=28-im->Code);
              GT_SetGadgetAttrs(StarLexGadgets[GDX_Y], StarLexWnd, NULL, GTTX_Text, ynum, TAG_END);
              ClearMap();
              showmap(X,Y);
              break;
            default:
              if ((StarLexWnd->MouseX>20)
                &&(StarLexWnd->MouseX<315)
                &&(StarLexWnd->MouseY>30)
                &&(StarLexWnd->MouseY<180))
              {
                x=((StarLexWnd->MouseX-20)/60)-2;
                y=2-((StarLexWnd->MouseY-30)/30);
                switch ((((StarLexWnd->MouseX-20)%60)/20*10)+((StarLexWnd->MouseY-30)%30)/10)
                {
                  case  0: z=-4; break;
                  case 10: z=-3; break;
                  case 20: z=-2; break;
                  case  1: z=-1; break;
                  case 11: z= 0; break;
                  case 21: z= 1; break;
                  case  2: z= 2; break;
                  case 12: z= 3; break;
                  case 22: z= 4; break;
                  default: z=99;
                }
                if ((Universe[30+x+X][30+y+Y][4+z]!=NULL)&&((struct System *)Universe[30+x+X][30+y+Y][4+z])->type=='*')
                {
                  sprintf(textarray, "%s (%3d,%3d,%2d)", ((struct System *)Universe[30+x+X][30+y+Y][4+z])->SysName, x+X, y+Y, z);
                  if (((struct System *)Universe[30+x+X][30+y+Y][4+z])->Comment)
                  {
                    if (((struct System *)Universe[30+x+X][30+y+Y][4+z])->type=='*')
                      sprintf(commenttext, "%s:%s", ((struct System *)Universe[30+x+X][30+y+Y][4+z])->SysName,
                                                     ((struct System *)Universe[30+x+X][30+y+Y][4+z])->Comment);
                    else
                      sprintf(commenttext, "Sector:%s", ((struct System *)Universe[30+x+X][30+y+Y][4+z])->Comment);
                    GT_SetGadgetAttrs(StarLexGadgets[GDX_BEM], StarLexWnd, NULL, GTLV_Labels, ~0, TAG_END);
                    ClearList(&list);
                    AddList(&list, commenttext);
                    GT_SetGadgetAttrs(StarLexGadgets[GDX_BEM], StarLexWnd, NULL, GTLV_Labels, &list, TAG_END);
                  }
                }
                else
                  sprintf(textarray, "(%3d,%3d,%2d)", x+X, y+Y, z);
                GT_SetGadgetAttrs(StarLexGadgets[GDX_INFO], StarLexWnd, NULL, GTTX_Text, textarray, TAG_END);
              }
              break;
          }
          break;
        case IDCMP_MENUPICK:
          selection=im->Code;
          while(selection!=MENUNULL)
          {
            menuNum = MENUNUM(selection);
            itemNum = ITEMNUM(selection);
            subNum  = SUBNUM (selection);
            switch(menuNum)
            {
              case 0: /* Project Menu */
                switch(itemNum)
                {
                  case 0: /* Load */
                          /* ClearMap();
                          showmap(X,Y);*/
                          break;
                  case 1: file=fopen("Universe", "w"); /* Save */
                          for(i=-30; i<=30; i++)
                            for(j=-30; j<=30; j++)
                              for(k=-4; k<=4; k++)
                              if (Universe[30+i][30+j][4+k]!=NULL)
                              {
                                if (((struct System *)Universe[30+i][30+j][4+k])->type=='*')
                                  fprintf(file, "\"%s\" (%3d,%3d,%2d)", ((struct System *)Universe[30+i][30+j][4+k])->SysName, i, j, k);
                                else
                                  fprintf(file, "Sector (%3d,%3d,%2d)", i, j, k);
                                if (((struct System *)Universe[30+i][30+j][4+k])->Comment)
                                  fprintf(file, ";%s\n", ((struct System *)Universe[30+i][30+j][4+k])->Comment);
                                else
                                  fprintf(file,"\n");
                                if (((struct System *)Universe[30+i][30+j][4+k])->Special=='!')
                                  fprintf(file, "Mark (%3d,%3d,%2d)\n", i, j, k);
                              }
                          fclose(file);
                          break;
                  case 2: file=fopen("Inputstars", "w"); /* Save As ASCII*/
                          for(i=-30; i<=30; i++)
                            for(j=-30; j<=30; j++)
                              for(k=-4; k<=4; k++)
                              if (Universe[30+i][30+j][4+k]!=NULL)
                                if (((struct System *)Universe[30+i][30+j][4+k])->type=='*')
                                {
                                  fprintf(file, "\"%s\" (%3d,%3d,%2d)", ((struct System *)Universe[30+i][30+j][4+k])->SysName, i, j, k);
                                  if (((struct System *)Universe[30+i][30+j][4+k])->Comment)
                                    fprintf(file, ";%s\n", ((struct System *)Universe[30+i][30+j][4+k])->Comment);
                                  else
                                    fprintf(file,"\n");
                                }
                          fclose(file);
                          break;
                  case 3: file=fopen("Stars.tex", "w"); /* Save As TeX */
                          tmp=1;
                          fprintf(file, "\\documentstyle[a4]{article}\n \\pagestyle{empty}\n \\def\\Star \#1,\#2,\#3,\#4;{\#1\&\#2\&\#3\&\#4\\\\}\n \\def\\Starx \#1,\#2,\#3,\#4;{\#1\&\#2\&\#3\&\#4\&}\n \\begin{document}\n\\small\n  \\begin{tabular}[12]{l@{\\quad(}r@{,}r@{,}r@{)\\qquad}l@{\\quad(}r@{,}r@{,}r@{)\\qquad}l@{\\quad(}r@{,}r@{,}r@{)}}\n");
                          for(i=-30; i<=30; i++)
                            for(j=-30; j<=30; j++)
                              for(k=-4; k<=4; k++)
                              if (Universe[30+i][30+j][4+k]!=NULL)
                              {
                                if (((struct System *)Universe[30+i][30+j][4+k])->type=='*')
                                {
                                  if (tmp%3)
                                    fprintf(file, "  \\Starx %s,%3d,%3d,%2d;\n", ((struct System *)Universe[30+i][30+j][4+k])->SysName, i, j, k);
                                  else
                                    fprintf(file, "  \\Star %s,%3d,%3d,%2d;\n", ((struct System *)Universe[30+i][30+j][4+k])->SysName, i, j, k);
                                  if (!(tmp++%168))
                                  {
                                    fprintf(file,"  \\end{tabular}\n \\newpage\n");
                                    fprintf(file, " \\begin{tabular}[12]{l@{\\quad(}r@{,}r@{,}r@{)\\qquad}l@{\\quad(}r@{,}r@{,}r@{)\\qquad}l@{\\quad(}r@{,}r@{,}r@{)}}\n");
                                  }
                                } 
                              }
                              fprintf(file,"  \\end{tabular}\n\\end{document}\n");
                          fclose(file);
                          break;
                  case 5: printf("New\n");
                          break;
                  case 7: printf("Quit\n");
                          notDone=0;
                          break;
                  default:
                    break;
                }
                break;
              case 1: /* Utilities Menu */
                switch(itemNum)
                {
                  case 0: /* Find System */
                          StringRequest(tmparray);
                          for(i=-30; i<=30; i++)
                            for(j=-30; j<=30; j++)
                              for(k=-4; k<=4; k++)
                              if (Universe[30+i][30+j][4+k]!=NULL)
                              {
                                if (((struct System *)Universe[30+i][30+j][4+k])->type=='*')
                                  if (!strncmp(tmparray,((struct System *)Universe[30+i][30+j][4+k])->SysName,strlen(tmparray)))
                                  {
                                    ClearMap();
                                    showmap(X=i,Y=j);
                                    sprintf(xnum, "%4d", X);
                                    sprintf(ynum, "%4d", Y);
                                    GT_SetGadgetAttrs(StarLexGadgets[GDX_XAXIS], StarLexWnd, NULL, GTSC_Top, X+28, TAG_END);
                                    GT_SetGadgetAttrs(StarLexGadgets[GDX_X], StarLexWnd, NULL, GTTX_Text, xnum, TAG_END);
                                    GT_SetGadgetAttrs(StarLexGadgets[GDX_YAXIS], StarLexWnd, NULL, GTSC_Top, 28-Y, TAG_END);
                                    GT_SetGadgetAttrs(StarLexGadgets[GDX_Y], StarLexWnd, NULL, GTTX_Text, ynum, TAG_END);                                    break;
                if ((Universe[30+x+X][30+y+Y][4+z]!=NULL)&&((struct System *)Universe[30+x+X][30+y+Y][4+z])->type=='*')
                {
                  sprintf(textarray, "%s (%3d,%3d,%2d)", ((struct System *)Universe[30+x+X][30+y+Y][4+z])->SysName, x+X, y+Y, z);
                  if (((struct System *)Universe[30+x+X][30+y+Y][4+z])->Comment)
                  {
                    if (((struct System *)Universe[30+x+X][30+y+Y][4+z])->type=='*')
                      sprintf(commenttext, "%s:%s", ((struct System *)Universe[30+x+X][30+y+Y][4+z])->SysName,
                                                     ((struct System *)Universe[30+x+X][30+y+Y][4+z])->Comment);
                    else
                      sprintf(commenttext, "Sector:%s", ((struct System *)Universe[30+x+X][30+y+Y][4+z])->Comment);
                    GT_SetGadgetAttrs(StarLexGadgets[GDX_BEM], StarLexWnd, NULL, GTLV_Labels, ~0, TAG_END);
                    ClearList(&list);
                    AddList(&list, commenttext);
                    GT_SetGadgetAttrs(StarLexGadgets[GDX_BEM], StarLexWnd, NULL, GTLV_Labels, &list, TAG_END);
                  }
                }
                else
                  sprintf(textarray, "(%3d,%3d,%2d)", x+X, y+Y, z);
                GT_SetGadgetAttrs(StarLexGadgets[GDX_INFO], StarLexWnd, NULL, GTTX_Text, textarray, TAG_END);
                                  }
                              }
                          break;

                  default:
                    break;
                }
              default:
                break;
            }
            selection=((struct MenuItem *)ItemAddress(StarLexMenus, (LONG)selection))->NextSelect;
          }
          break;
        case IDCMP_GADGETUP:
          switch(((struct Gadget *)im->IAddress)->GadgetID)
          {
            case GD_XAXIS:
              sprintf(xnum, "%4d", X=im->Code-28);
              GT_SetGadgetAttrs(StarLexGadgets[GDX_X], StarLexWnd, NULL, GTTX_Text, xnum, TAG_END);
              break;
            case GD_YAXIS: 
              sprintf(ynum, "%4d", Y=28-im->Code);
              GT_SetGadgetAttrs(StarLexGadgets[GDX_Y], StarLexWnd, NULL, GTTX_Text, ynum, TAG_END);
              break;
            case GD_MODE:
              mode=im->Code;
              break;
            default:
              break;
          }
          break;
        default:
	    break;
      }
      GT_ReplyIMsg(im);
    }
  }
  CloseStarLexWindow();
  CloseDownScreen();
  closelibs();
  return(0);
}

_abort()
{
  CloseStarLexWindow();
  CloseDownScreen();
  closelibs();
  exit(10);
}
