using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.Web.UI;
using System.Web.UI.DataVisualization.Charting;
using System.Web.UI.WebControls;

namespace LeafWeb.Web.Charter
{

	public partial class LeafWebCharter : UserControl
	{
		protected void ReadFile(StreamReader sr, ref String errMsg)
		{
			var pisOut = new PiscalOutput();
			if (!pisOut.ReadFromStream(sr, ref errMsg))
			{
				ErrorLBL.Text = errMsg;
				ErrorLBL.Visible = true;
				return;
			}
			Session["LeafChartData"] = pisOut;
			var aCopy = (PiscalOutput) Session["LeafChartData"];

			// The data was successfully read from the file.  We must now
			// display the curveIDs from the file and prompt the user to pick
			// one of them for charting.

			var curveDT = new DataTable();
			curveDT.Columns.Add(new DataColumn("curveID"));

			var curveData = pisOut.GetCurveData();
			for (var i = 0; i < curveData.Count; i++)
			{
				var aCurve = curveData[i];
				var dr = curveDT.NewRow();
				dr["curveID"] = aCurve.GetCurveId();
				curveDT.Rows.Add(dr);
			}

			//CurveDDL.DataSource = curveDT;
			//CurveDDL.DataTextField = "curveID";
			//CurveDDL.DataValueField = "curveID";
			//CurveDDL.DataBind();
		}


		// cntrlcomparison
		public void ProduceCharts(PiscalOutput pisOut)
		{
			// If the session has timed out, use the selected index from the GridView
			// to determine which job to chart.

			//		if (aFile.Name.Contains("cntrlcomparison"))
			//		{
			//			var sr = new StreamReader(aFile.OpenBinaryStream());
			//			var errorMessage = "";
			//			ReadFile(sr, ref errorMessage);
			//			sr.Close();
			//			break;
			//		}

			var curveData = pisOut.GetCurveData();
			var curve = curveData[1];

			var curveId = curve.GetCurveId();
			CurveSeries(curveId, curve.CndctFixedCmpPntFixedParams(), ChartChloro1, ChartInter1, "Internal conductance fixed, compensation point and M-M constants fixed");
			CurveSeries(curveId, curve.CndctFixedCmpPntEstimatedParams(), ChartChloro2, ChartInter2, "Internal conductance fixed, compensation point and M-M constants estimated");
			CurveSeries(curveId, curve.CndctEstimatedCmpPntFixedParams(), ChartChloro3, ChartInter3, "Internal conductance estimated, compensation point and M-M constants fixed");
			CurveSeries(curveId, curve.CndctEstimatedCmpPntEstimatedParams(), ChartChloro4, ChartInter4, "Internal conductance estimated, compensation point and M-M constants estimated");
		}

		private static Chart GetChart()
		{
			var font = new Font(new FontFamily("Trebuchet MS"), 12, FontStyle.Bold);

			var borderColor = Color.FromArgb(180, 26, 59, 105);
			var chart = new Chart
				{
					BackColor = Color.Transparent,
					Width = Unit.Pixel(700),
					Height = Unit.Pixel(500),
					BorderSkin = {SkinStyle = BorderSkinStyle.Emboss},
					BorderColor = borderColor
				};

			chart.Legends.Add(new Legend
				{
					Enabled = true,
					IsTextAutoFit = false,
					Name = "Default",
					Docking = Docking.Bottom,
					BackColor = Color.Transparent,
					Font = font
				});

			chart.ChartAreas.Add(new ChartArea
				{
					Name = "ChartArea1",
					BorderColor = Color.FromArgb(64, 64, 64, 64),
					BorderDashStyle = ChartDashStyle.Solid,
					BackSecondaryColor = Color.White,
					BackColor = Color.OldLace,
					ShadowColor = Color.Transparent,
					BackGradientStyle = GradientStyle.TopBottom,
					Area3DStyle = new ChartArea3DStyle
						{
							Rotation = 25,
							Perspective = 9,
							LightStyle = LightStyle.Realistic,
							Inclination = 40,
							IsRightAngleAxes = false,
							WallWidth = 3,
							IsClustered = false
						},
					AxisY = new Axis
						{
							LineColor = Color.FromArgb(64, 64, 64, 64),
							Title = "Net assimilation rate (umol/m2/s)",
							LabelStyle = {Font = font},
							MajorGrid = new Grid {LineColor = Color.FromArgb(64, 64, 64, 64)}
						}
				});

			var rubiscoLimited = new Series
			{
				MarkerSize = 8,
				BorderWidth = 3,
				XValueType = ChartValueType.Double,
				Name = "Rubisco-limited",
				ChartType = SeriesChartType.Point,
				MarkerStyle = MarkerStyle.Diamond,
				ShadowColor = Color.Black,
				BorderColor = borderColor,
				Color = Color.Red,
				ShadowOffset = 0,
				YValueType = ChartValueType.Double
			};	
			var rubpRegenerationLimited = new Series
			{
				MarkerSize = 9,
				BorderWidth = 3,
				XValueType = ChartValueType.Double,
				Name = "RuBP regeneration-limited",
				ChartType = SeriesChartType.Point,
				MarkerStyle = MarkerStyle.Circle,
				ShadowColor = Color.Black,
				BorderColor = borderColor,
				Color = Color.Blue,
				ShadowOffset = 0,
				YValueType = ChartValueType.Double
			};
			var acCurve = new Series
			{
				MarkerSize = 2,
				BorderWidth = 1,
				XValueType = ChartValueType.Double,
				Name = "acCurve",
				ChartType = SeriesChartType.Line,
				MarkerStyle = MarkerStyle.None,
				ShadowColor = Color.Black,
				BorderColor = borderColor,
				Color = Color.Red,
				ShadowOffset = 0,
				YValueType = ChartValueType.Double,
				IsVisibleInLegend = false
			};
			var ajCurve = new Series
			{
				MarkerSize = 2,
				BorderWidth = 1,
				XValueType = ChartValueType.Double,
				Name = "ajCurve",
				ChartType = SeriesChartType.Line,
				MarkerStyle = MarkerStyle.None,
				ShadowColor = Color.Black,
				BorderColor = borderColor,
				Color = Color.Blue,
				ShadowOffset = 0,
				YValueType = ChartValueType.Double,
				IsVisibleInLegend = false
			};
			var atCurve = new Series
			{
				MarkerSize = 2,
				BorderWidth = 1,
				XValueType = ChartValueType.Double,
				Name = "atCurve",
				ChartType = SeriesChartType.Line,
				MarkerStyle = MarkerStyle.None,
				ShadowColor = Color.Black,
				BorderColor = borderColor,
				Color = Color.Orange,
				ShadowOffset = 0,
				YValueType = ChartValueType.Double,
				IsVisibleInLegend = false
			};

			return chart;
		}

		private static void CurveSeries(string curveId, CurveParamSet paramSet, Chart chloroChart, Chart interChart, string chartTitle)
		{
			var paramSetAnet = paramSet.GetAnetMeasData();

			var anetMeasChloro1 = paramSetAnet[0];
			var anetMeasChloro2 = paramSetAnet[1];
			var anetMeasChloro3 = paramSetAnet[2];

			// Set the points for the symbol series for paramater set 1, chloroplastic
			setAnetMeasPoints(anetMeasChloro1, chloroChart.Series["Rubisco-limited"]);
			setAnetMeasPoints(anetMeasChloro2, chloroChart.Series["RuBP regeneration-limited"]);

			var tpuSeries = newTPUSeries(anetMeasChloro3);
			setAnetMeasPoints(anetMeasChloro3, tpuSeries);
			chloroChart.Series.Add(tpuSeries);

			var anetMeasInter1 = paramSetAnet[3];
			var anetMeasInter2 = paramSetAnet[4];
			var anetMeasInter3 = paramSetAnet[5];

			// Set the points for the symbol series for paramater set 1, intercellular
			setAnetMeasPoints(anetMeasInter1, interChart.Series["Rubisco-limited"]);
			setAnetMeasPoints(anetMeasInter2, interChart.Series["RuBP regeneration-limited"]);

			tpuSeries = newTPUSeries(anetMeasInter3);
			setAnetMeasPoints(anetMeasInter3, tpuSeries);
			interChart.Series.Add(tpuSeries);

			var acChloroList = paramSet.GetAcChloroData();
			var ajChloroList = paramSet.GetAjChloroData();
			var atChloroList = paramSet.GetAtChloroData();

			// Set the points on the asymptote curve for parameter set 1, chloroplast
			setAsymptotePoints(acChloroList, chloroChart.Series["acCurve"]);
			setAsymptotePoints(ajChloroList, chloroChart.Series["ajCurve"]);
			setAsymptotePoints(atChloroList, chloroChart.Series["atCurve"]);

			var acInterList = paramSet.GetAcInterData();
			var ajInterList = paramSet.GetAjInterData();
			var atInterList = paramSet.GetAtInterData();

			// Set the points on the asymptote curve for parameter set 1, intercellular
			setAsymptotePoints(acInterList, interChart.Series["acCurve"]);
			setAsymptotePoints(ajInterList, interChart.Series["ajCurve"]);
			setAsymptotePoints(atInterList, interChart.Series["atCurve"]);

			var axisFont = new Font("Times New Roman", 12, FontStyle.Bold);
			var titleFont = new Font("Times New Roman", 12, FontStyle.Bold);

			var title = new Title("LeafWeb curveID = " + curveId +
									 "\n" + chartTitle);
			title.Font = titleFont;
			chloroChart.Titles.Add(title);
			interChart.Titles.Add(title);

			chloroChart.ChartAreas["ChartArea1"].AxisX.TitleFont = axisFont;
			chloroChart.ChartAreas["ChartArea1"].AxisY.TitleFont = axisFont;

			interChart.ChartAreas["ChartArea1"].AxisX.TitleFont = axisFont;
			interChart.ChartAreas["ChartArea1"].AxisY.TitleFont = axisFont;
		}

		private static Series newTPUSeries(IReadOnlyCollection<XyPoint> data)
		{
			var seriesName = "TPU-limited";
			if (data.Count == 0)
				seriesName = "Curve Asymptote";
			var series3 = new Series(seriesName)
				{
					MarkerSize = 9,
					BorderWidth = 3,
					XValueType = ChartValueType.Double,
					ChartType = SeriesChartType.Point,
					MarkerStyle = MarkerStyle.Square,
					ShadowColor = Color.Black,
					BorderColor = Color.Black,
					Color = Color.Orange,
					ShadowOffset = 0,
					YValueType = ChartValueType.Double
				};

			return series3;
		}

		private static void setAnetMeasPoints(List<XyPoint> data, Series series)
		{
			// Set the points for the series from the ArrayList
			foreach (var xy in data)
			{
				series.Points.AddXY(xy.X, xy.Y);
			}
		}

		private static void setAsymptotePoints(List<XyPoint> data, Series series)
		{
			// Set the points for the series from the ArrayList
			foreach (var xy in data)
			{
				if ((xy.X != -9999) && (xy.Y != -9999))
				{
					series.Points.AddXY(xy.X, xy.Y);
				}
			}
		}
	}
}