/*****************************************************************************
 *
 * FILE:	webcal.c
 * DESCRIPTION:	Web Calendar CGI
 * DATE:	Sun, Apr  7 2002
 * UPDATE:	Sun, Aug 19 2007
 * AUTHOR:	Kouichi ABE (WALL) / 阿部康一
 * E-MAIL:	kouichi@MysticWALL.COM
 * URL:		http://www.MysticWALL.COM/
 * COPYRIGHT:	(c) 2002-2007 阿部康一／Kouichi ABE (WALL), All rights reserved.
 * COMPILE:	gcc -export-dynamic webcal.c -o webcal.cgi
 *		-I/usr/local/include -L/usr/local/lib
 *		-lcockatrice -lcatoblepas -lwkf -lmd
 * $Id: webcal.c,v 1.4 2007/08/19 16:50:38 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))
#define	LIEU_HOLIDAY	"振替休日"

/*****************************************************************************
 *
 *	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 String	months[] = { "1月", "2月", "3月", "4月", "5月", "6月",
			     "7月", "8月", "9月", "10月", "11月", "12月" };
  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);
  String	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, "%d年%s", year, months[month - 1]);
  html->thead.begin();
  html->tr.begin();
    html->th.attr.class	  = "caption";
    html->th.attr.colspan = 7;
    html->th.begin();
      if (month == 1) {
	asprintf(&s, "%s?year=%d&month=12", cgi->script_name, year - 1);
      }
      else {
	asprintf(&s, "%s?year=%d&month=%d", cgi->script_name, year, month - 1);
      }
      if (s) {
	html->a.attr.title = "先月";
	html->a.href(s, "&lt;");
	free(s);
      }
      html->printf("&nbsp;%s&nbsp;", title);
      if (month == 12) {
	asprintf(&s, "%s?year=%d&month=1", cgi->script_name, year + 1);
      }
      else {
	asprintf(&s, "%s?year=%d&month=%d", cgi->script_name, year, month + 1);
      }
      if (s) {
	html->a.attr.title = "来月";
	html->a.href(s, "&gt;");
	free(s);
      }
    html->th.end();
    html->th.attr.init();
  html->tr.end();
  html->thead.end();
  free(title);
  /* print a day of the week */
  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++) {
    const char *	rokuyou;
    const char *	sekki;

    rokuyou = cgi->date->getRokuyou(year, month, d);
    sekki   = cgi->date->get24Sekki(year, month, d);
    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.begin();
      html->span.attr.class = "holiday";
      asprintf(&s, "%d", d);
      if (s) {
	html->SPAN(s);
	free(s);
      }
      else {
	html->printf("$%d", d);
      }
      html->BR;
      html->span.attr.class = "dayinfo";
      html->SPAN(rokuyou);
      html->BR;
      html->span.attr.class = "dayname";
      html->SPAN(cgi->date->getFestivalName(year, month, d));
      if (sekki) {
	html->BR;
	html->span.attr.class = "dayinfo";
	html->SPAN(sekki);
      }
      html->td.end();
    }
    else {	/* Weekday */
      html->td.attr.class = d == today ? "today" : "weekday";
      if (lieu) {	/* Festival in lieu */
	html->td.attr.class = d == today ? "today" : "holiday";
	html->td.begin();
	html->span.attr.class = "holiday";
	asprintf(&s, "%d", d);
	if (s) {
	  html->SPAN(s);
	  free(s);
	}
	else {
	  html->printf("+%d", d);
	}
      }
      else {	/* Weekday */
	asprintf(&s, "%d", d);
	switch (i % WDAYS) {
	  case 0:	/* Sunday */
	    html->td.attr.class = d == today ? "today" : "sunday";
	    html->td.begin();
	    html->span.attr.class = "sunday";
	    if (s) {
	      html->SPAN(s);
	    }
	    else {
	      html->printf("*%d", d);
	    }
	    break;
	  case 6:	/* Saturday */
	    html->td.attr.class = d == today ? "today" : "saturday";
	    html->td.begin();
	    html->span.attr.class = "saturday";
	    if (s) {
	      html->SPAN(s);
	    }
	    else {
	      html->printf("#%d", d);
	    }
	    break;
	  default:
	    html->td.begin();
	    html->printf("%d", d);
	    break;
	}
	if (s) { free(s); }
      }
      html->BR;
      html->span.attr.class = "dayinfo";
      html->SPAN(rokuyou);
      if (lieu) {	/* Festival in lieu */
	lieu = false;
	html->BR;
	html->span.attr.class = "dayname";
	html->SPAN(LIEU_HOLIDAY);
      }
      if (sekki) {
	html->BR;
	html->span.attr.class = "dayinfo";
	html->SPAN(sekki);
      }
      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");

    html->html.attr.lang = "ja";
    html->html.begin();
      html->head.begin();
	html->meta.http_equiv("Content-Type", "text/html; charset=EUC-JP");
	html->meta.http_equiv("Content-Style-Type", "text/css");
	html->title("WebCalendar");
	html->style.begin("text/css", MEDIA_NONE);
	html->print("<!--\n\
body {\n\
  background: #ffffff;\n\
  color: #000000\n\
}\n\
img {\n\
  vertical-align: middle;\n\
  outline-width: 0;\n\
  border-width: 0;\n\
  border-style: none\n\
}\n\
a {\n\
  text-decoration: none\n\
}\n\
a:hover {\n\
  text-decoration: underline\n\
}\n\
table {\n\
  border: 1px solid #009900;\n\
  border-collapse: collapse\n\
}\n\
th.caption {\n\
  background: #ccffcc;\n\
  color: #009900;\n\
  border: 1px solid #009900;\n\
  text-align: center\n\
}\n\
th {\n\
  margin: 0;\n\
  border: 1px solid #009900;\n\
  padding: 1pt;\n\
  font-size: small;\n\
  font-weight: bold;\n\
  text-align: center\n\
}\n\
th.sunday {\n\
  color: #cc0000\n\
}\n\
th.weekday {\n\
  color: #000066\n\
}\n\
th.saturday {\n\
  color: #0000ff\n\
}\n\
td {\n\
  background: #ffffff;\n\
  color: #000066;\n\
  width: 7em;\n\
  height: 5em;\n\
  margin: 0;\n\
  border: 1px solid #009900;\n\
  padding: 1pt;\n\
  font-size: small;\n\
  font-weight: bold;\n\
  text-align: right;\n\
  vertical-align: top\n\
}\n\
td.today {\n\
  background: #ccff99\n\
}\n\
td.sunday, td.holiday {\n\
  background: #ffeeee\n\
}\n\
td.saturday {\n\
  background: #eef7ff\n\
}\n\
td.weekday {\n\
  background: #ffffff\n\
}\n\
span.sunday, span.holiday {\n\
  color: #cc0000\n\
}\n\
span.saturday {\n\
  color: #0000ff\n\
}\n\
span.dayname {\n\
  color: #cc0000;\n\
  font-size: xx-small\n\
}\n\
span.dayinfo {\n\
  color: #000000;\n\
  font-size: xx-small\n\
}\n\
-->");
	html->style.end();
      html->head.end();
      html->body.attr.lang = "ja";
      html->body.begin();
	makeCalendar(cgi, html, year, month);
      html->body.end();
    html->html.end();

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

  return 0;
}
