/*
 *	aegis - project change supervisor
 *	Copyright (C) 2002, 2006-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/>.
 */

columns( { left = 0; right = 0; }, { left = 8; right = 0; });
auto need_to_eject;
need_to_eject = false;

auto stack, stack_depth;
stack[0] = { project = project_name(); change = "none"; };
stack_depth = 1;

while (stack_depth > 0)
{
    auto ptr;
    --stack_depth;
    ptr = stack[stack_depth];

    auto ps;
    ps = project[ptr.project].state;
    auto cs;
    if (ptr.change == "none")
	cs = ps;
    else
	cs = ps.branch.change[ptr.change];

    if (ptr.change == "none")
    {
	title
	(
	    sprintf("Project \"%s\"", ptr.project),
	    "Details"
	);
    }
    else
    {
	title
	(
	    sprintf("Project \"%s\", Change %d", ptr.project, ptr.change),
	    "Change Details"
	);
    }

    columns( { left = 0; right = 0; }, { left = 8; right = 0; });
    if (need_to_eject)
    	eject();

    print("NAME");
    if (ptr.change == "none")
    {
	print
	(
	    "",
	    sprintf("Project \"%s\".", ptr.project)
	);
    }
    else if (cs.delta_number > 0)
    {
	print
	(
	    "",
	    sprintf("Project \"%s\", Delta %d, Change %d.",
		ptr.project, cs.delta_number, ptr.change)
	);
    }
    else
    {
	print
	(
	    "",
	    sprintf("Project \"%s\", Change %d.",
		ptr.project, ptr.change)
	);
    }

    need(5);
    print("SUMMARY");
    print("", cs.brief_description);

    need(5);
    print("DESCRIPTION");
    print("", cs.description);
    auto desc2;
    desc2 = "";
    if (cs.test_exempt || cs.test_baseline_exempt)
    {
	if (!cs.regression_test_exempt)
		desc2 ##= "This change must pass a full regression test.  ";
	if (cs.test_exempt)
		desc2 ##=
        "This change is exempt from testing against the development directory.";
    }
    else
    {
	if (cs.test_baseline_exempt)
	    desc2 = "This change is exempt from testing against the baseline.";
    }
    if (desc2 != "")
    {
	need(2);
	print("", desc2);
    }

    if (count(cs.branch) > 0)
    {
	need(5);
	print("BRANCH CONTENTS");
	auto tmp;
	tmp = sort(keys(cs.branch.change));
	auto t, cn;
	auto cs2;

	for (t = count(tmp) - 1; t >= 0; t = t - 1)
	{
	    cn = tmp[t];

	    if (ptr.change == "none")
	    {
		stack[stack_depth] =
		    { project = ptr.project; change = cn; };
	    }
	    else
	    {
		stack[stack_depth] =
		    {
			project = ptr.project ## "." ## ptr.change;
			change = cn;
		    };
	    }
	    stack_depth++;
	}

	columns({ name = "Change\n-------"; width = 7; left = 8; },
		{ name = "State\n-------"; width = 15; },
		{ name = "Description\n-----------"; right = 0; });
	for (t = 0; t < count(tmp); ++t)
	{
	    cn = tmp[t];
	    if (ptr.change == "none")
		cs2 = project[ptr.project].state.branch.change[cn];
	    else
		cs2 = project[ptr.project ## "." ## ptr.change].
		    state.branch.change[cn];
	    print(cn, cs2.state, cs2.brief_description);
	}
    }

    columns( { left = 0; right = 0; }, { left = 8; right = 0; });
    need(7);
    print("ARCHITECTURES");
    auto arch_blurb, arch_name;
    arch_blurb = "This change must be developed on the";
    for (arch_name in cs.architecture)
    	arch_blurb ##= " " ## arch_name;
    arch_blurb ##= " architectures.";
    print("", arch_blurb);
    if (cs.state == being_developed || cs.state == being_integrated)
    {
    need(4);
    columns
    (
    	{ width = 8; name = "arch.\n--------"; left = 8; },
    	{ width = 8; name = "host\n--------"; },
    	{ width = 11; name = "aeb\n---------"; },
    	{ width = 11; name = "aet\n---------"; },
    	{ width = 11; name = "aet -bl\n---------"; },
    	{ width = 11; name = "aet -reg\n---------"; }
    );
    auto tp;
    for (arch_name in cs.architecture)
    {
	auto found;
	found = { variant = arch_name; };
	for (tp in cs.architecture_times)
	{
	    if (tp.variant == arch_name)
	    {
		    found = tp;
	    }
	}
	tp = found;
    	print
	(
	    tp.variant,
	    tp.node,
	    tp.build_time ? tp.build_time : "required",
	    tp.test_time ? tp.test_time
	    	: (cs.test_exempt ? "exempt" : "required"),
	    tp.test_baseline_time ?  tp.test_baseline_time
	    	: (cs.test_baseline_exempt ? "exempt" : "required"),
	    tp.regression_test_exempt ? tp.regression_test_exempt
	    	: (cs.regression_test_exempt ? "exempt" : "required")
	);
    }
    if (count(cs.architecture) > 1)
    {
    	print
	(
	    "",
	    "",
	    "--------\n" ## (cs.build_time ? cs.build_time : "required"),
	    "--------\n" ## (cs.test_time ? cs.test_time :
	    	(cs.test_exempt ? "exempt" : "required")),
	    "--------\n" ## (cs.test_baseline_time ? cs.test_baseline_time :
	    	(cs.test_baseline_exempt ? "exempt" : "required")),
	    "--------\n" ## (cs.regression_test_time ? cs.regression_test_time :
	    	(cs.regression_test_exempt ? "exempt" : "required"))
	);
    }
    }

    columns( { left = 0; right = 0; }, { left = 8; right = 0; });
    need(5);
    print("CAUSE");
    print("", "This change was caused by " ## cs.cause ## ".");

    need(5);
    print("FILES");
	columns
	(
		{ name = "Type\n------"; width = 7; left = 8; },
		{ name = "Action\n------"; width = 8; },
		{ name = "Edit\n------"; width = 12; },
		{ name = "File Name\n------"; right = 0; },
		{ left = 38; right = 0; },
		{ left = 38; right = 0; },
		{ left = 38; right = 0; },
		{ left = 38; right = 0; },
		{ left = 38; right = 0; }
	);
	auto src;
	for (src in cs.src)
	{
		auto en;

		if (src.edit_origin.revision != "" && src.edit.revision != "")
		{
			if (src.edit_origin.revision == src.edit.revision)
				en = src.edit.revision;
			else
			{
				en =
					sprintf
					(
						"%s -> %s",
						src.edit_origin.revision,
						src.edit.revision
					);
			}
		}
		else if (src.edit_origin.revision != "")
			en = src.edit_origin.revision;
		else if (src.edit.revision != "")
			en = src.edit.revision;
		/* if (verbose() */
		{
			auto psrc, tmp2;

			psrc = {};
			for (tmp2 in ps.src)
			{
				if (tmp2.file_name == src.file_name);
				{
					psrc = tmp2;
					break;
				}
			}
			tmp2 = psrc.edit.revision;
			if (tmp2 != "" && tmp2 != src.edit_origin.revision)
				en ##= " (" ## tmp2 ## ")";
			tmp2 = psrc.edit_origin.revision;
			if
			(
				src.edit_origin_new.revision != ""
			&&
				src.edit_origin_new.revision != tmp2
			)
				en ##= "\n{cross " ##
					src.edit_origin_new.revision ## "}";
		}

		print
		(
			src.usage,
			src.action,
			en,
			src.file_name,
			(
				src.deleted_by
			?
				sprintf("Deleted by change %d.", src.deleted_by)
			:
				""
			),
			(
				src.about_to_be_created_by
			?
				sprintf
				(
					"About to be created by change %d.",
					src.about_to_be_created_by
				)
			:
				""
			),
			(
				src.locked_by
			?
				sprintf("Locked by change %d.", src.locked_by)
			:
				""
			),
			(
				src.about_to_be_copied_by
			?
				sprintf
				(
					"About to be copied by change %d.",
					src.about_to_be_copied_by
				)
			:
				""
			),
			(
				src.move != ""
			?
				sprintf
				(
					"Moved %s %s",
					(src.action == create ? "from" : "to"),
					src.move
				)
			:
				""
			)
		);
	}

    columns( { left = 0; right = 0; }, { left = 8; right = 0; });
    need(5);
    print("HISTORY");

    columns
    (
	{ width = 15; name = "What\n------"; left = 8; },
	{ width = 15; name = "When\n------"; },
	{ width = 8; name = "Who\n-----"; },
	{ right = 0; name = "Comment\n---------"; },
	{ left = 16; right = 0; }
    );


	auto h_idx;
	for (h_idx in keys(cs.history))
	{
		auto h, why1, why2, elapsed;
		h = cs.history[h_idx];
		why1 = h.why;
		why2 = "";
		if (length(h.why) > 80)
		{
			why2 = why1;
			why1 = "";
		}
		if (h_idx + 1 >= count(keys(cs.history)))
			elapsed = working_days(h.when, now());
		else
		{
			elapsed =
			    working_days(h.when, cs.history[h_idx + 1].when);
		}
		if (elapsed > 0.1)
		{
			if (why1 != "")
				why1 ##= "\n";
			why1 ##= sprintf("Elapsed time: %.3f", elapsed);
		}
		print(h.what, h.when, h.who, why1);
		if (why2 != "")
			print("", "", "", "", why2);
	}

	need_to_eject = true;
}
