/*
 *	aegis - project change supervisor
 *	Copyright (C) 1998, 2000-2003, 2005-2008 Peter Miller
 *
 *	This program 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 3 of the License, or
 *	(at your option) any later version.
 *
 *	This program 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 this program. If not, see
 *	<http://www.gnu.org/licenses/>.
 */

auto script_name;
script_name = getenv("SCRIPT_NAME");
if (script_name == "")
    script_name = "http://localhost/cgi-bin/aegis.cgi";
auto pn, p;
pn = project_name();
p = project[pn];

auto legend_used;
legend_used = { };

columns({width = 1000; });
print("Content-Type: text/html");
print("");
print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" "
        ## "\"http://www.w3.org/TR/REC-html40/loose.dtd\">");
print("<html><head>");
print("<meta name=\"ROBOTS\" content=\"NOINDEX, NOFOLLOW\">");
print("<meta name=\"GENERATOR\" content=\"" ## script_name ## "\">");
print("<meta http-equiv=\"Content-Type\" "
        ## "content=\"text/html; charset=ISO-8859-1\">");
print("<style type=\"text/css\"> "
        ## "tr.even-group { background-color: #CCCCCC; }"
        ## "body { background-color: white; }"
        ## "</style>");
/*
 * Netscape 4.x has numerous CSS bugs, two of which need mentioning.
 * 1. If a style sheet is not present Netscape says 404 Not found, when
 * it should silently ignore it.  2. Style sheets who's media is not
 * "screen" will be ignored.  Fortunately we can use (2) to get around (1).
 */
print("<link rel=\"stylesheet\" type=\"text/css\" href=\"/aedefault.css\" "
    ## "media=\"all\">");
auto stack, depth, n;
depth=0;
stack[depth] = project[pn].state.name;
while ("" != ( n = project[stack[depth]].state.parent_name )) {
  stack[++depth] = n;
}
while ( depth >= 0) {
    print("<link rel=\"stylesheet\" type=\"text/css\" href=\"/" ##
      stack[depth--] ## ".css\" " ## "media=\"all\">");
}
print("<title>");

auto cause_map;
cause_map =
{
	chain = "255+0+0";
	internal_bug = "255+255+0";
	external_bug = "192+192+0";
	internal_enhancement = "0+255+0";
	external_enhancement = "0+192+0";
	internal_improvement = "0+255+255";
	external_improvement = "0+192+192";
};

auto size_map;
size_map =
{
	create = 12;
	modify = 16;
	remove = 8;
};

/*
 * use the file prefix named on the command line
 * or the top level if not specified
 */
auto prefix;
if (count(arg) == 0)
	prefix = "";
else
	prefix = arg[0] ## "/";

print("Project " ## quote_html(pn) ## " Change Density by File" ##
    (prefix == "" ? "" : (", Directory " ## quote_html(prefix))));
print("</title></head><body><h1 align=center>");

auto href;
print("<a href=\"" ## script_name ## "\">Project</a>");
auto long_project_name;
auto prj_name_parts;
prj_name_parts = split(pn, '.');
href = script_name ## "?file@proj_menu+project@"
                   ## quote_url(prj_name_parts[0]);
long_project_name = "<a href=\"" ## href ## "\" >"
                   ## quote_html(prj_name_parts[0]) ## "</a>";
auto j;
for (j=1; j<count(prj_name_parts); j++)
{
    href ##= '.' ## prj_name_parts[j];
    long_project_name ##= ".<a href=\"" ## href ## "\" >"
                   ## quote_html(prj_name_parts[j]) ## "</a>";
};
long_project_name = "&ldquo;" ## long_project_name ## "&rdquo;,<br>";
/* HTTP limits lines to 510 characters */
for (j in wrap(long_project_name, 510))
    print(j);

auto long_dir_name, dir_parts;
if (prefix != "")
{
    href = script_name ## "?file@file_densi+project@" ## quote_url(pn);
    print("<a href=\"" ## href ## "\">Change Density by File</a><br>");
    long_dir_name = "Directory &ldquo;";
    href ##= "+";
    dir_parts = split(prefix, '/');
    for (j = 0; j < count(dir_parts) - 1; j++)
    {
        href ##= dir_parts[j];
        long_dir_name ##=
	    "<a href=\"" ## href ## "\" >" ##
	    quote_html(dir_parts[j]) ## "</a>/";
	href ##= "/";
    };
    long_dir_name ##= quote_html(dir_parts[count(dir_parts) - 1]) ## "&rdquo;";

    /* HTTP limits lines to 510 characters */
    for (j in wrap(long_dir_name, 510))
	print(j);
}
else
    print("Change Density by File");
print("</h1>");
print("<div class=\"information\">");
auto ps;
ps = project[project_name()].state;

/*
 * This will hold the cumulative statistics
 *	history[filename].is_a_directory
 *	history[filename].count[cause][action]
 */
auto remember;
remember = {};

/*
 * scan the project files for context
 */
auto ph, cs, cf, max, filename, is_a_directory;
for (cf in ps.src)
{
	if (cf.usage == build)
		continue;
	filename = cf.file_name;
	if (prefix != "")
	{
		if (substr(filename, 0, length(prefix)) != prefix)
			continue;
		filename = substr(filename, length(prefix), 99999);
	}
	filename = split(filename, "/");
	is_a_directory = (count(filename) > 1);
	filename = filename[0];

	if (typeof(remember[filename]) == "nul")
		remember[filename] = { count = {}; total = 0; };
	if (is_a_directory)
		remember[filename].is_a_directory = true;
}

/*
 * scan all completed changes
 * for any of the named files
 */
max = 1;
for (ph in ps.branch.history)
{
	cs = ps.branch.change[ph.change_number];
	for (cf in cs.src)
	{
		if (cf.usage == build && cf.action == modify)
			continue;
		filename = cf.file_name;
		if (prefix != "")
		{
			if (substr(filename, 0, length(prefix)) != prefix)
				continue;
			filename = substr(filename, length(prefix), 99999);
		}
		filename = split(filename, "/");
		is_a_directory = (count(filename) > 1);
		filename = filename[0];

		if (typeof(remember[filename]) == "nul")
			remember[filename] = { count = {}; total = 0; };
		if (is_a_directory)
			remember[filename].is_a_directory = true;
		if (typeof(remember[filename].count[cs.cause]) == "nul")
			remember[filename].count[cs.cause] = { total = 0; };
		remember[filename].count[cs.cause].total++;
		remember[filename].count[cs.cause][cf.action]++;
		remember[filename].total++;
		if (remember[filename].total > max)
			max = remember[filename].total;
		legend_used[cs.cause] = true;
	}
}

/*
 * print the accumulated history
 */
max = 300.0 / max;
auto cause, action;
auto width, height, clr;
print("<table align=center>");
for (filename in sort(keys(remember)))
{
	cf = remember[filename];

	if (cf.is_a_directory)
		href = "densi";
	else
		href = "menu";
	href = script_name ## "?file@file_" ## href ## "+" ##
		quote_url(prefix ## filename) ## "+project@" ##
		quote_url(project_name());

	print("<tr><td valign=top>");
	print("<a href=\"" ## href ## "\">");
	print("<span class=\"filename\">" ## quote_html(filename)
	    ## "</span></a>" ## (cf.is_a_directory ? "/" : ""));
	print("</td><td valign=top align=right>");
	print(cf.total);
	print("</td><td valign=top>");

	for (cause in [chain, internal_bug, internal_enhancement,
		internal_improvement, external_bug, external_enhancement,
		external_improvement])
	{
		for (action in [create, modify, remove])
		{
			clr = cause_map[cause];
			if (clr == "")
				clr = "191+191+191";
			if (typeof(cf.count[cause]) == "nul")
				cf.count[cause] = {};
			width = cf.count[cause][action];
			if (width <= 0)
				continue;
			width = round(width * max);
			if (width < 3)
				width = 3;
			height = size_map[action];
			if (height < 3)
				height = 3;
			href = script_name ## "?file@rect+" ## width ## "+" ##
				height ## "+color+" ## clr;
			print("<img src=\"" ## href ## "\" width=" ## width ##
				" height=" ## height ## ">");
		}
	}
	print("</td></tr>");
}
print("</table>");
print("</div>");

print("<hr>");
print("<div class=\"legend\">");
print("<h2 align=center>Legend</h2>");

print("<table align=center>");
print("<tr><th>Create</th><th>Modify</th><th>Remove</th><th>Cause</th></tr>");
for (cause in [chain, internal_bug, internal_enhancement,
	internal_improvement, external_bug, external_enhancement,
	external_improvement])
{
	if (!legend_used[cause])
	    continue;
	print("<tr>");
	clr = cause_map[cause];
	width = 30;
	for (action in [create, modify, remove])
	{
		print("<td valign=top align=center>");
		height = size_map[action];
		href = script_name ## "?file@rect+" ## width ## "+" ##
			height ## "+color+" ## clr;
		print("<img src=\"" ## href ## "\" width=" ## width ##
			" height=" ## height ## ">");
		print("</td>");
	}
	print("<td valign=top>");
	print(cause);
	print("</td></tr>");
}
print("</table>");
print("</div>");

print("<hr>");
print("<p align=\"center\" class=\"navbar\">[");
print("<a href=\"" ## script_name ## "\">Project List</a>");
print("|");
href = script_name ## "?file@proj_menu+project@" ## quote_url(pn);
print("<a href=\"" ## href ## "\">Project Menu</a>");
print("|");
href = script_name ## "?file@chan_list+project@" ## quote_url(pn);
print("<a href=\"" ## href ## "\">Change List</a>");
print("]</p>");

print("<hr>");
print("This page was generated " ## now() ## ".");
print("</body></html>");
