/*
** Copyright (C) 1988 by Jef Poskanzer and Craig Leres.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.

 *  Last modified: Thu Feb 24 12:27:07 1994 too
 *
 */

#include <math.h>
#include "amiga.h"
#include "original/tws.h"

#ifndef NULL
#define NULL 0
#endif

char *argv0;
int shadeflag = 0;
int demoflag = 0;
int reverseflag = 0;
int doubleflag = 0;

void	checkbitmapsize(int *, int *, int, int, int *, int *, int *, int *);
void	getbitmap(int, int, int, int, char **, int *, int *, int *, int *);

static void hackbits(struct tws * t, int w,
		     char *bits, int cx, int cy, int rx, int ry);

#define isdigit(a) (a >= '0' && a <= '9')

const char usage[] = "Usage: phoon " TEMPLATE "\n";
LONG args[CI_SIZE] = { 0 };

int start()
{
	int w, h, fm_w, fm_h, cx = 0, cy = 0, rx = 0, ry = 0;
	char *bits, *origbits;
	char *filename = NULL;
	int i, value;

	if (am_OpenLibraries() == FALSE)
	  return am_CloseLibraries(20);

	/*
	 * am_OpenLibraries did ReadArgs()
	 */
	if (args[CI_DOUBLE])
	  doubleflag = 1;

	filename = (char *)args[CI_FILE];  /* NULL if does not exist */

	if (args[CI_POSITION]) {
	  char * ptr = (char *)args[CI_POSITION];
	  for (i = 0; i < 4; i++) {
	    value = (int)ptr[2 * i];
		  switch (value) {
		  case '\0':    i = 5; continue;
		  case '-':     value = -1;     break;
		  case '+':     value =  1;     break;
		  default:	goto usage;
		  }
	    if (!isdigit(ptr[2 * i + 1])) {
	    usage:
	      Printf(usage);
	      return am_CloseLibraries(20);
	    }
	    value = value * (ptr[2 * i + 1] - '0');
	    switch (i) {
	    case 0:	cx = value;	break;
	    case 1:	cy = value;	break;
	    case 2:	rx = value;	break;
	    case 3:	ry = value;	break;
	    }
	  }
	}
	if (args[CI_REVERSE])
	  reverseflag = 1;

	if (args[CI_SHADE])
	  shadeflag = 1;

	Printf("Phase of the moon, Amiga version 2.1 (24.2.1994)\n");

	if (args[CI_GMTOFFSET]) {
	  if (gmtoffset != 32767)
	    Printf("*** Commmand line GMTOFFSET overruns Locale definition\n");
	  gmtoffset = -*(LONG *)args[CI_GMTOFFSET] * 60;
	}
	else if (gmtoffset == 32767) {
	  Printf("*** No GMTOFFSET defined... Used timezone is GMT\n");
	  gmtoffset = 0;
	}

	if (am_GetScreenSize(&w, &h) == FALSE)
	  return am_CloseLibraries(20);

	if ((bits = am_LoadFullmoon(&fm_w, &fm_h, filename)) == NULL)
	  return am_CloseLibraries(20);

	origbits = bits;
	checkbitmapsize(&w, &h, fm_w, fm_h, &cx, &cy, &rx, &ry);

	getbitmap(w, h, fm_w, fm_h, &bits, &cx, &cy, &rx, &ry);
	hackbits(dtwstime(), w, bits, cx, cy, rx, ry);

	am_MakeIFFile(w, h, bits, reverseflag);
	FreeVec(bits);
	return am_CloseLibraries(0);
}

short leftmask[16] = {
    0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
    0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
};
short rightmask[16] = {
    0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff, 0x00ff,
    0x007f, 0x003f, 0x000f, 0x001f, 0x0007, 0x0003, 0x0001, 0x0000,
};

static short  shades_0_bits[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
				  0x0000,0x0000};
static short  shades_1_bits[] = {0x0101,0x0000,0x0000,0x0000,0x0000,0x0000,
				  0x0000,0x0000};
static short  shades_2_bits[] = {0x0101,0x0000,0x0404,0x0000,0x0000,0x0000,
				  0x0000,0x0000};
static short  shades_3_bits[] = {0x0101,0x0000,0x0404,0x0000,0x8080,0x0000,
				  0x0000,0x0000};
static short  shades_4_bits[] = {0x0101,0x0000,0x0404,0x0000,0x8080,0x0000,
				  0x0000,0x1010};
static short  shades_5_bits[] = {0x0101,0x4040,0x0404,0x0000,0x8080,0x0000,
				  0x0000,0x1010};
static short  shades_6_bits[] = {0x0101,0x4040,0x0404,0x2020,0x8080,0x0000,
				  0x0000,0x1010};
static short  shades_7_bits[] = {0x0101,0x4040,0x0404,0x2020,0x8080,0x0000,
				  0x0101,0x1010};
static short  shades_8_bits[] = {0x0101,0x4040,0x0404,0x2020,0x8080,0x2020,
				  0x0101,0x1010};
static short  shades_9_bits[] = {0x0101,0x4040,0x0404,0x2020,0x8282,0x2020,
				  0x0101,0x1010};
static short shades_10_bits[] = {0x0101,0x4040,0x0404,0x2020,0x8282,0x2020,
				  0x0505,0x1010};
static short shades_11_bits[] = {0x0101,0x4040,0x0404,0x2020,0x8282,0x2020,
				  0x0505,0x5050};
static short shades_12_bits[] = {0x0101,0x4040,0x0505,0x2020,0x8282,0x2020,
				  0x0505,0x5050};
static short shades_13_bits[] = {0x0101,0x5050,0x0505,0x2020,0x8282,0x2020,
				  0x0505,0x5050};
static short shades_14_bits[] = {0x0101,0x5050,0x0505,0x2020,0x7575,0x2020,
				  0x0505,0x5050};
static short shades_15_bits[] = {0x0505,0x5050,0x0505,0x2020,0x7575,0x2020,
				  0x0505,0x5050};

short *shades_s[16] = {
    shades_0_bits,  shades_1_bits,  shades_2_bits,  shades_3_bits,
    shades_4_bits,  shades_5_bits,  shades_6_bits,  shades_7_bits,
    shades_8_bits,  shades_9_bits,  shades_10_bits, shades_11_bits,
    shades_12_bits, shades_13_bits, shades_14_bits, shades_15_bits };


static short  shaded_0_bits[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
				  0x0000,0x0000};
static short  shaded_1_bits[] = {0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,
				  0x0000,0x0000};
static short  shaded_2_bits[] = {0x0003,0x0000,0x0030,0x0000,0x0000,0x0000,
				  0x0000,0x0000};
static short  shaded_3_bits[] = {0x0003,0x0000,0x0030,0x0000,0xc000,0x0000,
				  0x0000,0x0000};
static short  shaded_4_bits[] = {0x0003,0x0000,0x0030,0x0000,0xc000,0x0000,
				  0x0000,0x0300};
static short  shaded_5_bits[] = {0x0003,0x3000,0x0030,0x0000,0xc000,0x0000,
				  0x0000,0x0300};
static short  shaded_6_bits[] = {0x0003,0x3000,0x0030,0x0c00,0xc000,0x0000,
				  0x0000,0x0300};
static short  shaded_7_bits[] = {0x0003,0x3000,0x0030,0x0c00,0xc000,0x0000,
				  0x0003,0x0300};
static short  shaded_8_bits[] = {0x0003,0x3000,0x0030,0x0c00,0xc000,0x0c00,
				  0x0003,0x0300};
static short  shaded_9_bits[] = {0x0003,0x3000,0x0030,0x0c00,0xc00c,0x0c00,
				  0x0003,0x0300};
static short shaded_10_bits[] = {0x0003,0x3000,0x0030,0x0c00,0xc00c,0x0c00,
				  0x0033,0x0300};
static short shaded_11_bits[] = {0x0003,0x3000,0x0030,0x0c00,0xc00c,0x0c00,
				  0x0033,0x3300};
static short shaded_12_bits[] = {0x0003,0x3000,0x0033,0x0c00,0xc00c,0x0c00,
				  0x0033,0x3300};
static short shaded_13_bits[] = {0x0003,0x3300,0x0033,0x0c00,0xc00c,0x0c00,
				  0x0033,0x3300};
static short shaded_14_bits[] = {0x0003,0x3300,0x0033,0x0c00,0x3f33,0x0c00,
				  0x0033,0x3300};
static short shaded_15_bits[] = {0x0033,0x3300,0x0033,0x0c00,0x3f33,0x0c00,
				  0x0033,0x3300};

short *shades_d[16] = {
    shaded_0_bits,  shaded_1_bits,  shaded_2_bits,  shaded_3_bits,
    shaded_4_bits,  shaded_5_bits,  shaded_6_bits,  shaded_7_bits,
    shaded_8_bits,  shaded_9_bits,  shaded_10_bits, shaded_11_bits,
    shaded_12_bits, shaded_13_bits, shaded_14_bits, shaded_15_bits };

#if 0
unsigned short v1[] = {
  0, 1507, 2131, 2610, 3014, 3369, 3691, 3986, 4261, 4519, 4763, 4996,
  5217, 5430, 5635, 5832, 6023, 6208, 6388, 6562, 6732, 6898, 7060,
  7218, 7373, 7524, 7673, 7819, 7962, 8102, 8240, 8376, 8509, 8640,
  8770, 8897, 9023, 9147, 9269, 9389, 9508, 9626, 9742, 9856, 9970,
  10082, 10193, 10302, 10410, 10518, 10624, 10729, 10833, 10936, 11037,
  11138, 11239, 11338, 11436, 11533, 11630, 11726, 11821, 11915
  };
#endif

unsigned short v[] = {
  4763, 6732, 8240, 9508,
  10624, 11630, 12553, 13411, 14215, 14974, 15695, 16381, 17039, 17670,
  18278, 18865, 19432, 19982, 20516, 21034, 21539, 22031, 22511, 22979,
  23437, 23885, 24323, 24753, 25174, 25586, 25991, 26389, 26780, 27164,
  27541, 27912, 28278, 28637, 28992, 29340, 29684, 30023, 30357, 30687,
  31011, 31332, 31649, 31961, 32269, 32574, 32875, 33172, 33465, 33756,
  34043, 34326, 34607, 34884, 35158, 35429, 35698, 35963, 36226, 36486,
  36743, 36998, 37250, 37500, 37747, 37992, 38235, 38475, 38713, 38948,
  39182, 39413, 39643, 39870, 40095, 40318, 40539, 40759, 40976, 41191,
  41405, 41617, 41827, 42035, 42242, 42446, 42650, 42851, 43051, 43249,
  43446, 43641, 43834, 44026, 44216, 44405, 44593, 44779, 44963, 45146,
  45328, 45509, 45688, 45865, 46041, 46216, 46390, 46562, 46733, 46903,
  47072, 47239, 47405, 47570, 47734, 47896, 48058, 48218, 48377, 48535,
  48692, 48847, 49002, 49155, 49307, 49459, 49609, 49758, 49906, 50053,
  50199, 50344, 50488, 50631, 50773, 50914, 51054, 51193, 51331, 51468,
  51605, 51740, 51874, 52008, 52140, 52272, 52402, 52532, 52661, 52789,
  52916, 53042, 53168, 53292, 53416, 53539, 53661, 53782, 53902, 54022,
  54140, 54258, 54375, 54491, 54607, 54721, 54835, 54948, 55061, 55172,
  55283, 55393, 55502, 55611, 55718, 55825, 55932, 56037, 56142, 56246,
  56349, 56452, 56554, 56655, 56755, 56855, 56954, 57052, 57150, 57247,
  57343, 57439, 57534, 57628, 57722, 57814, 57907, 57998, 58089, 58179,
  58269, 58358, 58446, 58534, 58621, 58707, 58793, 58878, 58962, 59046,
  59129, 59212, 59294, 59375, 59456, 59536, 59615, 59694, 59772, 59850,
  59927, 60004, 60079, 60155, 60229, 60303, 60377, 60450, 60522, 60594,
  60665, 60735, 60805, 60875, 60944, 61012, 61080, 61147, 61213, 61279,
  61345, 61410, 61474, 61538, 61601, 61664, 61726, 61787, 61848, 61909,
  61969, 62028, 62087, 62145, 62203, 62260, 62317, 62373, 62429, 62484,
  62539, 62593, 62646, 62699, 62752, 62804, 62855, 62906, 62956, 63006,
  63056, 63104, 63153, 63201, 63248, 63295, 63341, 63387, 63432, 63477,
  63521, 63565, 63608, 63651, 63693, 63735, 63776, 63817, 63857, 63897,
  63936, 63975, 64013, 64051, 64088, 64125, 64161, 64197, 64233, 64267,
  64302, 64336, 64369, 64402, 64434, 64466, 64498, 64529, 64559, 64589,
  64619, 64648, 64677, 64705, 64732, 64759, 64786, 64812, 64838, 64863,
  64888, 64912, 64936, 64960, 64983, 65005, 65027, 65048, 65069, 65090,
  65110, 65130, 65149, 65168, 65186, 65204, 65221, 65238, 65254, 65270,
  65285, 65300, 65315, 65329, 65342, 65355, 65368, 65380, 65392, 65403,
  65414, 65424, 65434, 65444, 65453, 65461, 65469, 65477, 65484, 65491,
  65497, 65502, 65508, 65513, 65517, 65521, 65524, 65527, 65530, 65532,
  65533, 65534, 65535, 65535
  };

#ifdef PI
#undef PI
#endif
#define PI 3.14159265358979323846  /* Assume not near black hole or in
				      Tennessee */

double jtime(), phase();

static void hackbits(struct tws * t, int w,
		     char * bits, int cx, int cy, int rx, int ry)
{
  double jd, angphase, cphase, aom, cdist, cangdia, csund, csuang;
  short i, *plane;
  short xleft, xright, wxright, bxright, wxleft, bxleft;
  long fxleft, fxright, *fxdir, *fxoth;
  float cap, ratio;
  short shadeindex, shade, **shades;
  const short ww = (w + 15) >> 4;
  
  jd = jtime( t );
  
  angphase = phase( jd, &cphase, &aom, &cdist, &cangdia, &csund, &csuang);
  cap = cos( angphase );
  /* Hack to figure approximate earthlighting. */
  if ( cphase < 0.1 ) cphase = 0.1;
  if ( cphase > 0.9 ) cphase = 0.9;
  ratio = (1.0 - cphase) / cphase;  /* ratio varies from 9.0 to 0.111 */
  shadeindex = (int)( ratio / 9.0 * 15.9999 );
  
  shade = 0x0000;
  shades = doubleflag? shades_d: shades_s;

  plane = ((short *)bits) + (cy - ry) * ww;

  if (angphase >= 0.0 && angphase < PI) {
    fxdir = &fxright;
    fxoth = &fxleft;
  }
  else {
    fxdir = &fxleft;
    fxoth = &fxright;
  }
  for (i = 0; i < 2 * ry; i++) {
    if (i > ry)
      fxright = rx * v[753 - i * 377 / ry];
    else
      fxright = rx * v[i * 377 / ry];

/*    printf("%ld, %ld, %d \n", i * 377 / ry, 753 - i * 377 / ry, fxright); */
    fxleft = - fxright;

    *fxdir = ((int)((double)*fxdir * cap)) >> 16;
    *fxoth >>= 16;

    xright = fxright + cx;
    xleft = fxleft + cx;
    
    wxright = xright >> 4;
    bxright = xright & 15;
    
    wxleft = xleft >> 4;
    bxleft = xleft & 15;
    
    plane += ww;
    
    if ( shadeflag )
      shade = shades[shadeindex][i & 7];
    
    if (wxleft == wxright)
      plane[wxleft] &= leftmask[bxleft] | shade | rightmask[bxright];
    else {
      short x;
      plane[wxleft] &= leftmask[bxleft] | shade;
      for (x = wxleft + 1; x < wxright; x++)	plane[x] &= shade;
      plane[wxright] &= rightmask[bxright] | shade;
    }
  }
}
