/* revolution.c: conversion des dates du calendrier révolutionnaire
   en dates "normales" (calendrier grégorien)

   Programme original: Benoit Marchandise <marchanb@mail.com>
   Adaptation Amiga  : Roland Florac <roland.florac!fnac.net>

Revolution is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

Revolution is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Revolution; see the file COPYING.  If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/


#include <stdio.h>
#include <libraries/gtlayout.h>
#include <proto/exec.h>
#include <proto/gtlayout_protos.h>
#include <pragmas/gtlayout_pragmas.h>

enum { VENDÉMIAIRE = 31, BRUMAIRE, FRIMAIRE, NIVOSE, PLUVIOSE, VENTOSE,
    GERMINAL, FLORÉAL, PRAIRIAL, MESSIDOR, THERMIDOR, FRUCTIDOR,
    AN_I, AN_II, AN_III, AN_IV, AN_V, AN_VI, AN_VII, AN_VIII, AN_IX,
    AN_X, AN_XI, AN_XII, AN_XIII, AN_XIV,
    VERTU, GÉNIE, LABOUR, RAISON, RÉCOMPENSE, RÉVOLUTION,
    DATE_CALENDRIER_GRÉGORIEN, DATE_CALENDRIER_RÉVOLUTIONNAIRE
};

static struct Library * GTLayoutBase;

/*********************************************
 *   Global variables			     *
 *********************************************/

static long Year = 1, Month = 1, Day = 1;
static char GregorianDate[40], RevolutionaryDate[40];

static char * mois[] = { "Vendémiaire", "Brumaire", "Frimaire", "Nivôse", "Pluviôse", "Ventôse", "Germinal", "Floréal", "Prairial",
    "Messidor", "Thermidor", "Fructidor" };
static char * an[] = { " 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9","10","11","12","13","14" };
static char * jour[] = { " 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9","10",
    "11","12","13","14","15","16","17","18","19","20",
    "21","22","23","24","25","26","27","28","29","30" };
static char * jourcompl[] = { "Vertu", "Génie", "Labour", "Raison", "Récompense", "Révolution" };


static void ShowRevolutionary (struct LayoutHandle * h)
{
    if (Month == 13)
	sprintf (RevolutionaryDate, "   %s An %s", jourcompl[Day-1], an[Year-1]);
    else
	sprintf (RevolutionaryDate, "   %s %s An %s", jour[Day-1], mois[Month-1], an[Year-1]);
    LT_SetAttributes (h, DATE_CALENDRIER_RÉVOLUTIONNAIRE, GTTX_Text, RevolutionaryDate, TAG_END);
}

/**
 * Computes the gregorian date and displays it. Uses Year, Month & Day global variables.
 * the algorithm is based on the Emacs Calendar.
 */
static void ShowGregorian (struct LayoutHandle * h)
{

    long lastDay[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    /* The absolute date is the number of days elapsed since the Gregorian date 1701-01-01.*/
    long absoluteDate = 33136	/* Absolute date of start of French Revolutionary calendar =
				   September 22, 1792. */
	+ 365 * Year
	+ (Year / 4)            /* leap year */
	+ 30 * (Month - 1)      /* Days in prior months this year */
	+ Day;

    long n100 = absoluteDate / 36524;
    long d2 = absoluteDate % 36524;
    long n4 = d2 / 1461;
    long d3 = d2 % 1461;
    long n1 = d3 / 365;
    long gday = (d3 % 365) + 1;
    long gmonth = 0;
    long gyear = 1701 + n100 * 100 + n4 * 4 + n1;

    if (n1 == 4)
    {
	gday = 31;
	gmonth = 12;
	gyear--;
    }
    else
    {
	/* Month calculation */

	if (gyear % 4 == 0 && gyear != 1700)
	{
	    lastDay[1]++;
	}

	while (gday > lastDay[gmonth])
	{
	    gday -= lastDay[gmonth];
	    gmonth++;
	}
	gmonth++;
    }

    /* Display the dates */
    ShowRevolutionary (h);
    sprintf (GregorianDate, "        %2d/%2d/%4d", gday, gmonth, gyear);
    LT_SetAttributes (h, DATE_CALENDRIER_GRÉGORIEN, GTTX_Text, GregorianDate, TAG_END);
}

/**
 * The main entry point of the application.
 *
 */
long main ()
{
    struct LayoutHandle * h;
    struct Window * w;
    long i, col;

    if (GTLayoutBase = OpenLibrary ("gtlayout.library", 36))
    {
	if (h = LT_CreateHandleTags (NULL, TAG_DONE))
	{
	    LT_New (h, LA_Type, VERTICAL_KIND, TAG_DONE);
	    {
		LT_New (h, LA_Type, VERTICAL_KIND, LAGR_Frame, TRUE, TAG_DONE);
		{
		    LT_New (h, LA_Type, VERTICAL_KIND, LA_LabelText, "Jour", TAG_DONE);
		    {
			for (i = 0;  i <= 2;  i++)
			{
			    LT_New (h, LA_Type, HORIZONTAL_KIND, TAG_DONE);
			    {
				for (col = 0;  col < 10;  col++)
				    LT_New (h, LA_Type, BUTTON_KIND,
					LA_LabelText, jour[col + i * 10],
					LA_ID,	      col + i * 10 + 1,
				    TAG_DONE);
				LT_EndGroup (h);
			    }
			}
			LT_EndGroup (h);
		    }
		    LT_New (h,  LA_Type, HORIZONTAL_KIND, LA_LabelText, "Jours complémentaires", TAG_DONE);
		    {
			for (col = 0;  col <= 2;  col++)
			{
			    LT_New (h, LA_Type, VERTICAL_KIND, TAG_DONE);
			    {
				for (i = 0;  i <= 3;  i += 3)
				    LT_New (h, LA_Type, BUTTON_KIND,
					LA_LabelText, jourcompl[col + i],
					LA_ID,	      VERTU+col+i,
					LA_Chars,     11,
				    TAG_DONE);
				LT_EndGroup (h);
			    }
			}
			LT_EndGroup (h);
		    }
		    LT_New (h,  LA_Type, HORIZONTAL_KIND, LA_LabelText, "Mois", TAG_DONE);
		    {
			for (col = 0;  col <= 3;  col++)
			{
			    LT_New (h, LA_Type, VERTICAL_KIND, TAG_DONE);
			    {
				for (i = 0;  i <= 8;  i += 4)
				    LT_New (h, LA_Type,    BUTTON_KIND,
					LA_LabelText, mois[col + i],
					LA_ID,	      VENDÉMIAIRE + col + i,
					LA_Chars,     11,
				    TAG_DONE);
				LT_EndGroup (h);
			    }
			}
			LT_EndGroup (h);
		    }
		    LT_New (h, LA_Type, HORIZONTAL_KIND, LA_LabelText, "Année", TAG_DONE);
		    {
			for (i = 0;  i < 14;  i++)
			    LT_New (h, LA_Type,    BUTTON_KIND,
				LA_LabelText, an[i],
				LA_ID,	      AN_I + i,
			    TAG_DONE);
			LT_EndGroup (h);
		    }
		}
		LT_EndGroup (h);
		LT_New (h, LA_Type, HORIZONTAL_KIND, LAGR_Spread, TRUE, LAGR_SameSize, TRUE, LAGR_Frame, TRUE, TAG_DONE);
		{
		    LT_New (h, LA_Type, TEXT_KIND,
			LA_LabelText, "Calendrier révolutionnaire",
			LA_LabelPlace, PLACE_Above,
			LA_ID, DATE_CALENDRIER_RÉVOLUTIONNAIRE,
			GTTX_Border, TRUE,
		    TAG_DONE);
		    LT_New (h, LA_Type, TEXT_KIND,
			LA_LabelText, "Calendrier Grégorien",
			LA_LabelPlace, PLACE_Above,
			LA_ID,	    DATE_CALENDRIER_GRÉGORIEN,
			GTTX_Border, TRUE,
		    TAG_DONE);
		    LT_EndGroup (h);
		}
		LT_EndGroup (h);
	    }
	    if (w = LT_Build (h,
		LAWN_Title,	"Conversion dates calendriers Révolutionnaire/Grégorien",
		LAWN_IDCMP,	IDCMP_CLOSEWINDOW,
		WA_DepthGadget,     TRUE,
		WA_DragBar,	    TRUE,
		WA_Activate,	    TRUE,
		WA_CloseGadget, TRUE,
	    TAG_DONE))
	    {
		struct IntuiMessage * Message;
		struct Gadget * MsgGadget;
		ULONG MsgClass;
		BOOL Done = FALSE;

		ShowGregorian (h);
		do
		{
		    WaitPort(w->UserPort);

		    while (Message = LT_GetIMsg (h))
		    {
			MsgClass    = Message->Class;
			MsgGadget   = Message->IAddress;
			LT_ReplyIMsg (Message);

			switch (MsgClass)
			{
			    case IDCMP_CLOSEWINDOW:

				Done = TRUE;
				break;

			    case IDCMP_GADGETUP:

				if (MsgGadget->GadgetID >= 1  &&  MsgGadget->GadgetID <= 30)
				{
				    Day = MsgGadget->GadgetID;
				    if (Month == 13)
					Month = 1;
				    ShowGregorian (h);
				}
				else if (MsgGadget->GadgetID >= VERTU  &&  MsgGadget->GadgetID <= RÉVOLUTION)
				{
				    if (MsgGadget->GadgetID == RÉVOLUTION)
				    {
					if (! (Year % 4 == 3))
					{
					    LT_SetAttributes (h, DATE_CALENDRIER_RÉVOLUTIONNAIRE, GTTX_Text, "Ans III, VII et XI seuls", TAG_END);
					    break;
					}
				    }
				    Month = 13;
				    Day = MsgGadget->GadgetID - VERTU + 1;
				    ShowGregorian (h);
				}
				else if (MsgGadget->GadgetID >= VENDÉMIAIRE  &&  MsgGadget->GadgetID <= FRUCTIDOR)
				{
				    if (Month == 13)
					Day = 1;
				    Month = MsgGadget->GadgetID - VENDÉMIAIRE + 1;
				    ShowGregorian (h);
				}
				else if (MsgGadget->GadgetID >= AN_I  &&  MsgGadget->GadgetID <= AN_XIV)
				{
				    Year = MsgGadget->GadgetID - AN_I + 1;
				    if (Month == 13)
					if (Day == 6)
					    if (! (Year % 4 == 3))
						Month = Day = 1;
				    ShowGregorian (h);
				}
				break;
			}
		    }
		}
		while (! Done);
	    }
	    LT_DeleteHandle (h);
	}
	CloseLibrary (GTLayoutBase);
	return 0;
    }
    return 10;
}
