/*****************************************************************************
 *
 * FILE:	ajaxcal.c
 * DESCRIPTION:	Web Calendar CGI for Ajax
 * DATE:	Sun, Aug 19 2007
 * UPDATE:	Tue, Aug 21 2007
 * AUTHOR:	Kouichi ABE (WALL) / 阿部康一
 * E-MAIL:	kouichi@MysticWALL.COM
 * URL:		http://www.MysticWALL.COM/
 * COPYRIGHT:	(c) 2007 阿部康一／Kouichi ABE (WALL), All rights reserved.
 * COMPILE:	gcc -export-dynamic ajaxcal.c -o ajaxcal.cgi
 *		-I/usr/local/include -L/usr/local/lib
 *		-lcockatrice -lcatoblepas -lwkf -lmd
 * $Id: ajaxcal.c,v 1.2 2007/08/20 20:51:18 kouichi Exp $
 *
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <cockatrice.h>
#include <catoblepas.h>

/*****************************************************************************
 *
 *	Macros and structures definition
 *
 *****************************************************************************/
#define	LEAP(x)	((((x) % 4 == 0) && ((x) % 100 != 0)) || ((x) % 400 == 0))

/*****************************************************************************
 *
 *	Local functions definition
 *
 *****************************************************************************/
static void	makeCalendar(CGI *, HTML *, int, int);

/*****************************************************************************
 *
 *	Local variables declaration
 *
 *****************************************************************************/

/*****************************************************************************
 *
 *	definition of functions
 *
 *****************************************************************************/

/*
 * FUNCTION NAME:	makeCalendar
 * DESCRIPTION:		make a calendar
 * ARGUMENTS:		CGI, HTML, year, month
 * RETURN VALUE:	none
 */
static void
makeCalendar(cgi, html, year, month)
	register CGI *	cgi;
	register HTML *	html;
	int		year;
	int		month;
{
#define	WDAYS	7
  static char *	wday[] = {"日", "月", "火", "水", "木", "金", "土"};
  static int	mday[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

  int		today	 = -1;
  int		firstDay = cgi->date->getDayOfTheWeek(year, month, 1);
  int		leap	 = LEAP(year);
  char *	title;
  bool		lieu;
  int		d;	/* days */
  int		i;
  int		j;
  char *	s;	/* working pointer */

  /* set day of today */
  if (year == cgi->date->year() && month == cgi->date->month()) {
    today = cgi->date->day();
  }

  mday[2] += leap;	/* revise */

  html->table.attr.border = 0;
  html->table.attr.cellspacing = "0";
  html->table.attr.cellpadding = "0";
  html->table.begin();
  /* table header */
  asprintf(&title, "<span id='year'>%d</span>年<span id='month'>%d</span>月",
	   year, month);
  html->thead.begin();
  html->tr.begin();
    html->th.attr.class	  = "caption";
    html->th.attr.colspan = 7;
    html->th.begin();
      if (month == 1) {
	asprintf(&s, "ajax.update('%s?year=%d&month=12','ajaxcal');",
		 cgi->script_name, year - 1);
      }
      else {
	asprintf(&s, "ajax.update('%s?year=%d&month=%d','ajaxcal');",
		 cgi->script_name, year, month - 1);
      }
      if (s) {
	html->img.event.onclick = s;
	html->IMG("/images/arrowleft.png", "先月", "16", "16");
	free(s);
	html->img.event.onclick = NULL;	/* clear event */
      }
      html->printf("&nbsp;%s&nbsp;", title);
      if (month == 12) {
	asprintf(&s, "ajax.update('%s?year=%d&month=1','ajaxcal');",
		 cgi->script_name, year + 1);
      }
      else {
	asprintf(&s, "ajax.update('%s?year=%d&month=%d','ajaxcal');",
		 cgi->script_name, year, month + 1);
      }
      if (s) {
	html->img.event.onclick = s;
	html->IMG("/images/arrowright.png", "来月", "16", "16");
	free(s);
	html->img.event.onclick = NULL;	/* clear event */
      }
    html->th.end();
    html->th.attr.init();
  html->tr.end();
  html->thead.end();
  free(title);
  /* table footer */
  html->tfoot.begin();
  html->tr.begin();
    html->td.attr.colspan = 7;
    html->td.attr.class	  = "footer";
    html->td.begin();
      do {
	const char *	rokuyou;
	const char *	sekki;
	const char *	holiday;
	int		ty = cgi->date->year();
	int		tm = cgi->date->month();
	int		td = cgi->date->day();

	rokuyou = cgi->date->getRokuyou(ty, tm, td);
	sekki   = cgi->date->get24Sekki(ty, tm, td);
	holiday = cgi->date->getFestivalName(ty, tm, td);
	html->printf("%d/%02d/%d&nbsp;", ty, tm, td);
	html->printf("%s", rokuyou);
	if (holiday || sekki) { html->BR; }
	if (holiday) {
	  html->span.attr.class = "holiday";
	  html->SPAN(holiday);
	}
	if (sekki) {
	  html->printf("&nbsp;%s", sekki);
	}
      } while (0);
    html->td.end();
  html->tr.end();
  html->tfoot.end();

  /* print a day of the week */
  html->td.attr.init();
  html->tr.begin();
  for (i = 0; i < WDAYS; i++) {
    switch (i) {
      case 0:  html->th.attr.class = "sunday";   break;
      case 6:  html->th.attr.class = "saturday"; break;
      default: html->th.attr.class = "weekday";  break;
    }
    html->th.begin();
      html->printf("%s", wday[i]);
    html->th.end();
  }
  html->tr.end();
  /* print a days of a month */
  html->tr.begin();
  html->td.attr.class = "weekday";
  for (i = 0; i < firstDay; i++) {	/* padding */
    html->td.begin();
      html->print("&nbsp;");
    html->td.end();
  }
  for (lieu = false, d = 1; d <= mday[month]; d++, i++) {
    if (i % WDAYS == 0) {
      html->tr.begin();
    }
    if (cgi->date->isFestival(year, month, d)) {	/* Festival ?*/
      if (cgi->date->getDayOfTheWeek(year, month, d) == 0) {	/* Sunday? */
	lieu = true;
      }
      html->td.attr.class = d == today ? "today" : "holiday";
      html->td.attr.title = cgi->date->getFestivalName(year, month, d);
      html->td.begin();
      html->printf("%d", d);
      html->td.end();
    }
    else {	/* Weekday */
      html->td.attr.class = d == today ? "today" : "weekday";
      html->td.attr.title = NULL;
      if (lieu) {	/* Festival in lieu */
	lieu = false;
	html->td.attr.class = d == today ? "today" : "holiday";
	html->td.begin();
	html->printf("%d", d);
      }
      else {	/* Weekday */
	asprintf(&s, "%d", d);
	switch (i % WDAYS) {
	  case 0:	/* Sunday */
	    html->td.attr.class = d == today ? "today" : "sunday";
	    break;
	  case 6:	/* Saturday */
	    html->td.attr.class = d == today ? "today" : "saturday";
	    break;
	  default:
	    break;
	}
	html->td.begin();
	html->printf("%d", d);
	if (s) { free(s); }
      }
      html->td.end();
    }
    if (i % WDAYS == 6) {
      html->tr.end();
    }
  }
  mday[2] -= leap;	/* end of revised */
  /* padding */
  html->td.attr.class = "weekday";
  j = i % WDAYS == 0 ? 0 : WDAYS - (i % WDAYS);
  for (i = 0; i < j; i++) {
    html->td.begin();
    html->print("&nbsp;");
    html->td.end();
  }
  html->tr.end();
  html->table.end();
}


int
main(argc, argv)
	int	argc;
	char *	argv[];
{
  CGI *	cgi;	/* cgi object */
  HTML *	html;
  int	year;
  int	month;

  cgi = newCGI(CC_MODULE_DATE);
  if (cgi == NULL) {
    fprintf(stderr, "Error: %d\n", cgi_errno);
    return -1;
  }

  html = newHTML401(HTML4_Strict);
  if (html) {
    if (cgi->param("year") != NULL) {
      year = atoi(cgi->param("year"));
    }
    else {
      year = cgi->date->year();
    }

    if (cgi->param("month") != NULL) {
      month = atoi(cgi->param("month"));
    }
    else {
      month = cgi->date->month();
    }

    cgi->header("text/html; charset=EUC-JP");

    makeCalendar(cgi, html, year, month);

    html->done();
  }
  cgi->done();

  return 0;
}
