/* Copyright (c) 1993 by Sanjay Ghemawat */
/*
 * Routines to speed up dateeditor.
 */
#include <stdio.h>
#include <string.h>
#include <tcl.h>

#include "Date.h"
#include "Month.h"
#include "WeekDay.h"

#include "cal_tcl.h"
#include "calendar.h"
#include "calfile.h"
#include "commands.h"
#include "collect.h"
#include "item_tcl.h"
#include "misc_tcl.h"

static int monday_first();

/*
 * requires	argc/argv === <cmd> <canvas> <date>
 *		Canvas has 42 text items with tags ranging from
 *		=1 to =42.  The text items are arranged in a grid
 *		7 wide by 6 high.  The numbers increase from left to
 *		right and then top to bottom.  Therefore, the top-left
 *		item has tag =1, rop-right item has tag =7, and the
 *		bottom-right item tag =42.  Each one of these 42 items
 *		also has the tag "Day".
 *
 * effects	Configures items so that their text contents correspond
 *		to the day of the month that should be displayed at that
 *		item (under the assumption that the month  named by <date>
 *		is being displayed).
 */
int Cmd_MonthDays(ClientData, Tcl_Interp* tcl, int argc, char* argv[]) {
    if (argc != 3) {
	TCL_Error(tcl, "illegal number of arguments");
    }

    int dateDays;
    if (Tcl_GetInt(tcl, argv[2], &dateDays) != TCL_OK) {
	return TCL_ERROR;
    }
    Date date(dateDays);
    Date first(1, date.GetMonth(), date.GetYear());

    int start = first.GetWDay().Index();
    if (monday_first()) {
	start = ((start + 5)%7) + 1;
    }
    int finish = start + first.GetMonth().Size(first.GetYear()) - 1;

    char* canvas = argv[1];
    if (Tcl_VarEval(tcl, canvas, " itemconfig Day -text {}", NULL) != TCL_OK) {
	return TCL_ERROR;
    }

    for (int i = start; i <= finish; i++) {
	char str[100];
	sprintf(str, "=%d -text {%4d}", i, i - start + 1);
	if (Tcl_VarEval(tcl, canvas, " itemconfig ", str, NULL) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

    TCL_Return(tcl, "");
}

/*
 * requires	argc/argv === <cmd> <canvas> <date>
 *		Canvas has 42 text items with tags ranging from
 *		=1 to =42.  The text items are arranged in a grid
 *		7 wide by 6 high.  The numbers increase from left to
 *		right and then top to bottom.  Therefore, the top-left
 *		item has tag =1, rop-right item has tag =7, and the
 *		bottom-right item tag =42.  Each one of these 42 items
 *		also has the tag "Day".
 *
 * effects	Configures items so that they have tag "interest" iff
 *		the corresponding date has interesting items.  Also
 *		configure the items to have tag "holiday" iff the
 *		corresponding date has an item marked as a holiday item.
 */
int Cmd_InterestTags(ClientData, Tcl_Interp* tcl, int argc, char* argv[]) {
    if (argc != 3) {
	TCL_Error(tcl, "illegal number of arguments");
    }

    int dateDays;
    if (Tcl_GetInt(tcl, argv[2], &dateDays) != TCL_OK) {
	return TCL_ERROR;
    }
    Date date(dateDays);
    Date first(1, date.GetMonth(), date.GetYear());
    int size = first.GetMonth().Size(first.GetYear());
    Date last = first + size - 1;

    /* Number of initial blank entries in display */
    int blanks = first.GetWDay().Index() - 1;
    if (monday_first()) {
	blanks = (blanks + 6)%7;
    }

    int interest[43], holiday[43];
    for (int i = 1; i <= 42; i++) {
	interest[i] = 0;
	holiday[i] = 0;
    }

    Date today = Date::Today();
    Occurrences list;
    collect_occurrences(list, first, last, 0);
    for (i = 0; i < list.size(); i++) {
	int index = (list[i].date - first) + blanks + 1;

	switch (list[i].item->value()->Hilite()) {
	  case Item::AlwaysHilite:
	    interest[index] = 1;
	    break;
	  case Item::ExpireHilite:
	    if (list[i].date >= today) {
		interest[index] = 1;
	    }
	    break;
	  case Item::HolidayHilite:
	    holiday[index] = 1;
	    break;
	  default:
	    break;
	}
    }

    char* canvas = argv[1];

    /* Add interest to everything that we are still interested in */
    for (i = 1; i <= 42; i++) {
	char str[100];
	sprintf(str, "=%d", i);

	if (interest[i]) {
	    if (Tcl_VarEval(tcl, canvas, " addtag interest withtag ", str,
			    NULL) != TCL_OK) {
		return TCL_ERROR;
	    }
	}

	if (holiday[i]) {
	    if (Tcl_VarEval(tcl, canvas, " addtag holiday withtag ", str,
			    NULL) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
    }

    TCL_Return(tcl, "");
}

static int monday_first() {
    Calendar* cal = calendar_instance->main->GetCalendar();
    return ((strcmp(cal->GetOption("MondayFirst"), "1") == 0) ? 1 : 0);
}
