<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Drawing.Imaging" %>
<!-- #include file = "inc.aspx" -->

<script language="C#" runat="server">

String sql;
DbUtil dbutil;
Security security;
int scale = 1;

///////////////////////////////////////////////////////////////////////
void Page_Load(Object sender, EventArgs e)
{

	Util.do_not_cache(Response);
	dbutil = new DbUtil();
	security = new Security();
	security.check_security(dbutil, HttpContext.Current, Security.ANY_USER_OK);

	if (security.user.is_admin || security.user.can_use_reports)
	{
		//
	}
	else
	{
		Response.Write ("You are not allowed to use this page.");
		Response.End();
	}


	string string_id = Util.sanitize_integer(Request["id"]);
	string view = Request["view"];

	string scale_string = Request["scale"];

	if (scale_string == null || scale_string == "")
	{
		scale = 1;
	}
	else
	{
		scale = Convert.ToInt32(scale_string);
	}

	sql = @"select rp_desc, rp_sql, rp_chart_type
		from reports
		where rp_id = $id";

	sql = sql.Replace("$id", string_id);

	DataRow dr = dbutil.get_datarow (sql);

	string rp_sql = (string) dr["rp_sql"];

	// replace the magic pseudo variable
	rp_sql = rp_sql.Replace("$ME", Convert.ToString(security.user.usid));

	DataSet ds = dbutil.get_dataset (rp_sql);

	if (ds.Tables[0].Rows.Count > 0)
	{
		if (view == "data")
		{
			create_table((string) dr["rp_desc"], ds);
		}
		else
		{
			if ((string) dr["rp_chart_type"] == "pie")
			{
				create_pie_chart((string) dr["rp_desc"], ds);
			}
			else if ((string) dr["rp_chart_type"] == "bar")
			{
				create_bar_chart((string) dr["rp_desc"], ds);
			}
			else if ((string) dr["rp_chart_type"] == "line")
			{
				// we need at least two values to draw a line
				if (ds.Tables[0].Rows.Count > 1)
				{
					create_line_chart((string) dr["rp_desc"], ds);
				}
			}
			else {
				create_table((string) dr["rp_desc"], ds);
			}
		}
	}
	else
	{
		create_table((string) dr["rp_desc"], ds);
	}

}




///////////////////////////////////////////////////////////////////////
void create_line_chart(string title, DataSet ds)
{
	int chart_width=640 / scale;
	int chart_height=300 / scale;
	int chart_top_margin = 10 / scale; // gap between highest bar and border of chart

	int x_axis_text_offset = 8 / scale; // gap between edge and start of x axis text
	int page_top_margin = 40 / scale; // gape between chart and top of page

	int max_grid_lines = 20 / scale;

	Font fontTitle = new Font("Verdana", 12, FontStyle.Bold);

	Font fontLegend = new Font("Verdana", 8);
	int page_bottom_margin = 3 * fontLegend.Height;
	int page_left_margin = (4 * fontLegend.Height) + x_axis_text_offset ;  // where the y axis text goes


	// find the max of the y axis so we know how to scale the data
	float max = 0.0F;
	float tmp;
	int i;
	for (i = 0; i < ds.Tables[0].Rows.Count; i++)
	{
		tmp = Convert.ToSingle(ds.Tables[0].Rows[i][1]);
		if (tmp > max) {max = tmp;};
	}

	float vertical_scale_factor = (chart_height - chart_top_margin)/max;

	// determine how the horizontal grid lines should be

	int grid_line_interval = 1;
	if (max > 1) {
		while (max / grid_line_interval > max_grid_lines)
		{
			grid_line_interval *= 10 / scale;
		}
	}


	// Create a Bitmap instance
	Bitmap objBitmap = new Bitmap(
		page_left_margin + chart_width,  // total width
		page_top_margin + fontTitle.Height + chart_height + page_bottom_margin);  // total height

	Graphics objGraphics = Graphics.FromImage(objBitmap);


	// white overall background
	objGraphics.FillRectangle(
		new SolidBrush(Color.White), // yellow
		0,0,
		page_left_margin + chart_width, // far left
		page_top_margin + fontTitle.Height + chart_height + page_bottom_margin);  // bottom

	// gray chart background
	objGraphics.FillRectangle(
		new SolidBrush(Color.FromArgb(204,204,204)), // gray
		page_left_margin, page_top_margin + fontTitle.Height,
		page_left_margin + chart_width,
		chart_height);


	SolidBrush blackBrush = new SolidBrush(Color.Black);


	// draw title
	objGraphics.DrawString(
		title,
		fontTitle,
		blackBrush,
		x_axis_text_offset,
		fontTitle.Height / 2);

	int y;
	int chart_bottom = page_top_margin + fontTitle.Height + chart_height;

	Pen black_pen = new Pen(Color.Black, 1);

	for (i = 0; i < max; i+= grid_line_interval)
	{

		y = (int)(i * vertical_scale_factor);

		// y axis label
		objGraphics.DrawString(
				Convert.ToString(i),
				fontLegend,
				blackBrush,
				x_axis_text_offset, (chart_bottom-y) - (fontLegend.Height/2));

		// grid line
		objGraphics.DrawLine(
			black_pen,
			page_left_margin,
			chart_bottom-y,
			page_left_margin + chart_width,
			chart_bottom-y);
	}

/*
	// draw high water mark
	y = (int)(max * vertical_scale_factor);

	objGraphics.DrawString(
			Convert.ToString(i),
			fontLegend,
			blackBrush,
			x_axis_text_offset, (chart_bottom-y) - (fontLegend.Height/2));

	// grid line
	objGraphics.DrawLine(
		black_pen,
		page_left_margin,
		chart_bottom-y,
		page_left_margin + chart_width,
		chart_bottom-y);
*/

	// draw lines
	int line_length = chart_width / (ds.Tables[0].Rows.Count-1);
	int x = page_left_margin;

	int x_axis_text_y = chart_bottom + (page_bottom_margin/2) - (fontLegend.Height/2);

	Pen blue_pen = new Pen(Color.FromArgb(0,0,204), 2);
	SolidBrush blue_brush = new SolidBrush(Color.FromArgb(0,0,204));
	int prev_x_axis_label = -99999;

	for (i = 1; i < ds.Tables[0].Rows.Count; i++)
	{

		float data1 = Convert.ToSingle((int)ds.Tables[0].Rows[i-1][1]);
		float data2 = Convert.ToSingle((int)ds.Tables[0].Rows[i][1]);

		int value_y1 = (int)(data1 * vertical_scale_factor);
		int value_y2 = (int)(data2 * vertical_scale_factor);

		objGraphics.DrawLine(
			blue_pen,
			x, chart_bottom - value_y1,
			x + line_length, chart_bottom - value_y2);

		objGraphics.FillEllipse(
			blue_brush,
			(x + line_length)-3, (chart_bottom - value_y2) - 3,
			6, 6);

		// draw x axis labels
		int x_val = (int) ds.Tables[0].Rows[i][0];

		if (x - prev_x_axis_label > 50) // space them apart, so they don't bump into each other
		{

			// the little line so that the label points to the the data point
			objGraphics.DrawLine(
				black_pen,
				x, chart_bottom,
				x, chart_bottom+14);

			objGraphics.DrawString(
				Convert.ToString(x_val),
				fontLegend,
				blackBrush,
				x, x_axis_text_y);

			prev_x_axis_label = x;
		}


		x += line_length;
	}

	// Since we are outputting a Jpeg, set the ContentType appropriately
	Response.ContentType = "image/jpeg";

	// Save the image to a file
	objBitmap.Save(Response.OutputStream, ImageFormat.Jpeg);

	// clean up...
	objGraphics.Dispose();
	objBitmap.Dispose();


}


///////////////////////////////////////////////////////////////////////
void create_bar_chart(string title, DataSet ds)
{
	int chart_width=640 / scale;
	int chart_height=300 / scale;
	int chart_top_margin = 10 / scale; // gap between highest bar and border of chart

	int x_axis_text_offset = 8 / scale; // gap between edge and start of x axis text
	int page_top_margin = 40 / scale; // gape between chart and top of page

	int max_grid_lines = 20 / scale;

	Font fontTitle = new Font("Verdana", 12, FontStyle.Bold);

	Font fontLegend = new Font("Verdana", 8);
	int page_bottom_margin = 3 * fontLegend.Height;
	int page_left_margin = (4 * fontLegend.Height) + x_axis_text_offset ;  // where the y axis text goes


	// find the max of the y axis so we know how to scale the data
	float max = 0.0F;
	float tmp;
	int i;
	for (i = 0; i < ds.Tables[0].Rows.Count; i++)
	{
		tmp = Convert.ToSingle(ds.Tables[0].Rows[i][1]);
		if (tmp > max) {max = tmp;};
	}

	float vertical_scale_factor = (chart_height - chart_top_margin)/max;

	// determine how the horizontal grid lines should be

	int grid_line_interval = 1;
	if (max > 1) {
		while (max / grid_line_interval > max_grid_lines)
		{
			grid_line_interval *= 10 / scale;
		}
	}


	// Create a Bitmap instance
	Bitmap objBitmap = new Bitmap(
		page_left_margin + chart_width,  // total width
		page_top_margin + fontTitle.Height + chart_height + page_bottom_margin);  // total height

	Graphics objGraphics = Graphics.FromImage(objBitmap);


	// white overall background
	objGraphics.FillRectangle(
		new SolidBrush(Color.White), // yellow
		0,0,
		page_left_margin + chart_width, // far left
		page_top_margin + fontTitle.Height + chart_height + page_bottom_margin);  // bottom

	// gray chart background
	objGraphics.FillRectangle(
		new SolidBrush(Color.FromArgb(204,204,204)), // gray
		page_left_margin, page_top_margin + fontTitle.Height,
		page_left_margin + chart_width,
		chart_height);

	SolidBrush blackBrush = new SolidBrush(Color.Black);

	// draw title
	objGraphics.DrawString(
		title,
		fontTitle,
		blackBrush,
		x_axis_text_offset,
		fontTitle.Height / 2);

	int y;
	int chart_bottom = page_top_margin + fontTitle.Height + chart_height;

	Pen black_pen = new Pen(Color.Black, 1);

	for (i = 0; i < max; i+= grid_line_interval)
	{

		y = (int)(i * vertical_scale_factor);

		// y axis label
		objGraphics.DrawString(
			Convert.ToString(i),
			fontLegend,
			blackBrush,
			x_axis_text_offset, (chart_bottom-y) - (fontLegend.Height/2));

		// grid line
		objGraphics.DrawLine(
			black_pen,
			page_left_margin,
			chart_bottom-y,
			page_left_margin + chart_width,
			chart_bottom-y);
	}

/*
	// draw high water mark
	y = (int)(max * vertical_scale_factor);

	objGraphics.DrawString(
		Convert.ToString(i),
		fontLegend,
		blackBrush,
		x_axis_text_offset, (chart_bottom-y) - (fontLegend.Height/2));

	// grid line
	objGraphics.DrawLine(
		black_pen,
		page_left_margin,
		chart_bottom-y,
		page_left_margin + chart_width,
		chart_bottom-y);
*/

	// draw bars
	int bar_space = chart_width / ds.Tables[0].Rows.Count;
	int bar_width = (int) (.70F * bar_space);
	int x = (int) (.30F * bar_space);
	x += page_left_margin;

	int x_axis_text_y = chart_bottom + (page_bottom_margin/2) - (fontLegend.Height/2);
	Brush blue_brush = new SolidBrush(Color.FromArgb(0,0,204));

	for (i = 0; i < ds.Tables[0].Rows.Count; i++)
	{

		float data = Convert.ToSingle((int)ds.Tables[0].Rows[i][1]);

		int bar_height = (int)(data * vertical_scale_factor);

		objGraphics.FillRectangle(
			blue_brush,
			x, chart_bottom - bar_height,
			bar_width,
			bar_height);

		objGraphics.DrawString(
			Convert.ToString(ds.Tables[0].Rows[i][0]),
			fontLegend,
			blackBrush,
			x, x_axis_text_y);


		x += bar_width;
		x += (int) (.30F * bar_space);
	}

	// Since we are outputting a Jpeg, set the ContentType appropriately
	Response.ContentType = "image/jpeg";

	// Save the image to a file
	objBitmap.Save(Response.OutputStream, ImageFormat.Jpeg);

	// clean up...
	objGraphics.Dispose();
	objBitmap.Dispose();


}




///////////////////////////////////////////////////////////////////////
void create_pie_chart(string title, DataSet ds)
{

	int width = 240;
	int page_top_margin = 15;

	// [corey] - I downloaded this code from MSDN, the URL below, and modified it.
	// http://msdn.microsoft.com/msdnmag/issues/02/02/ASPDraw/default.aspx

	// We need to connect to the database and grab information for the
	// particular columns for the particular table


	// find the total of the numeric data
	float total = 0.0F, tmp;
	int i;
	for (i=0; i < ds.Tables[0].Rows.Count; i++)
	{
		tmp = Convert.ToSingle(ds.Tables[0].Rows[i][1]);
		total += tmp;
	}

	// we need to create fonts for our legend and title
	Font fontLegend = new Font("Verdana", 10);

	Font fontTitle = new Font("Verdana", 12, FontStyle.Bold);
	int titleHeight = fontTitle.Height + page_top_margin;

	// We need to create a legend and title, how big do these need to be?
	// Also, we need to resize the height for the pie chart, respective to the
	// height of the legend and title

	int row_gap = 6;
	int start_of_rect = 8;
	int rect_width = 14;
	int rect_height = 16;

	int row_height;
	if (rect_height > fontLegend.Height) row_height = rect_height; else row_height = fontLegend.Height;
	row_height += row_gap;

	int legendHeight = row_height * (ds.Tables[0].Rows.Count+1);
	int height = width + legendHeight + titleHeight + page_top_margin;
	int pieHeight = width;	// maintain a one-to-one ratio

	// Create a rectange for drawing our pie
	Rectangle pieRect = new Rectangle(0, titleHeight, width, pieHeight);

	// Create our pie chart, start by creating an ArrayList of colors
	ArrayList colors = new ArrayList();

	colors.Add(new SolidBrush(Color.FromArgb(204,204,255)));
	colors.Add(new SolidBrush(Color.FromArgb(051,051,255)));
	colors.Add(new SolidBrush(Color.FromArgb(204,204,204)));
	colors.Add(new SolidBrush(Color.FromArgb(153,153,255)));
	colors.Add(new SolidBrush(Color.FromArgb(153,153,153)));
	colors.Add(new SolidBrush(Color.FromArgb(000,204,000)));

	Random rnd = new Random();
	for (i = 0; i < ds.Tables[0].Rows.Count-6; i++)
		colors.Add(new SolidBrush(Color.FromArgb(rnd.Next(255), rnd.Next(255), rnd.Next(255))));

	float currentDegree = 0.0F;

	// Create a Bitmap instance
	Bitmap objBitmap = new Bitmap(width, height);
	Graphics objGraphics = Graphics.FromImage(objBitmap);

	SolidBrush blackBrush = new SolidBrush(Color.Black);

	// Put a white backround in
	objGraphics.FillRectangle(new SolidBrush(Color.White), 0, 0, width, height);
	for (i = 0; i < ds.Tables[0].Rows.Count; i++)
	{
		objGraphics.FillPie(
			(SolidBrush) colors[i],
			pieRect,
			currentDegree,
			Convert.ToSingle(ds.Tables[0].Rows[i][1]) / total * 360);

		// increment the currentDegree
		currentDegree += Convert.ToSingle(ds.Tables[0].Rows[i][1]) / total * 360;
	}

	// Create the title, centered
	StringFormat stringFormat = new StringFormat();
	stringFormat.Alignment = StringAlignment.Center;
	stringFormat.LineAlignment = StringAlignment.Center;

	objGraphics.DrawString(title, fontTitle, blackBrush,
				 new Rectangle(0, 0, width, titleHeight), stringFormat);


	// Create the legend
	objGraphics.DrawRectangle(
		new Pen(Color.Gray, 1),
		0,
		height - legendHeight,
		width-4,
		legendHeight-1);

	int y = height - legendHeight + row_gap;

	for (i = 0; i < ds.Tables[0].Rows.Count; i++)
	{

		objGraphics.FillRectangle(
			(SolidBrush) colors[i],
			start_of_rect,  // x
			y,
			rect_width,
			rect_height);

		objGraphics.DrawString(
			Convert.ToString(ds.Tables[0].Rows[i][0])
			+ " - " +
			Convert.ToString(ds.Tables[0].Rows[i][1]),
			fontLegend,
			blackBrush,
			start_of_rect + rect_width + 4,
			y);

		y += rect_height + row_gap;


	}

	// display the total
	objGraphics.DrawString(
		"Total: " + Convert.ToString(total),
		fontLegend,
		blackBrush,
		start_of_rect + rect_width + 4,
		y);

	// Since we are outputting a Jpeg, set the ContentType appropriately
	Response.ContentType = "image/jpeg";


	// Save the image to a file
	objBitmap.Save(Response.OutputStream, ImageFormat.Jpeg);

	// clean up...
	objGraphics.Dispose();
	objBitmap.Dispose();
}

///////////////////////////////////////////////////////////////////////
void create_table(string title, DataSet ds)
{

    Response.Write("<link rel=StyleSheet href=btnet.css type=text/css>");
	Response.Write("<s" + "cript");
	Response.Write(" type=text/javascript language=JavaScript src=sortable.js>");
	Response.Write("</s" + "cript>");

	Response.Write ("<body style='background: white;'><div class=align><table border=0><tr><td>");

    Response.Write("<h2>" + title + "</h2>");

	if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
	{
		SortableHtmlTable.create_from_dataset(
			Response, ds, "", "");

	}
	else
	{
		Response.Write ("<font size=+1>The database query for this report returned zero rows.</font>");
	}


}

</script>