// Copyright (C) 2003 Daisuke Arai <darai@users.sourceforge.jp>
// 
// This program is part of Protra.
//
// Protra 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/>.
// 
// $Id: ProfitGraphBox.cs,v 1.2 2007-12-27 08:34:39 panacoran Exp $

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Windows.Forms;

namespace PtSim.Controls
{
	/// <summary>
	/// 利益曲線を描くためのコントロールです。
	/// </summary>
	public class ProfitGraphBox : System.Windows.Forms.UserControl
	{
		/// <summary>
		/// 描画対象となる利益のリスト
		/// </summary>
		private ProfitList profitList;

		/// <summary>
		/// 必要なデザイナ変数です。
		/// </summary>
		private System.ComponentModel.Container components = null;

		/// <summary>
		/// コンストラクタ
		/// </summary>
		public ProfitGraphBox()
		{
			// この呼び出しは、Windows.Forms フォーム デザイナで必要です。
			InitializeComponent();

			// TODO: InitForm を呼び出しの後に初期化処理を追加します。

		}

		/// <summary>
		/// 使用されているリソースに後処理を実行します。
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Component Designer generated code
		/// <summary>
		/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
		/// コード エディタで変更しないでください。
		/// </summary>
		private void InitializeComponent()
		{
			// 
			// ProfitGraphBox
			// 
			this.Name = "ProfitGraphBox";
			this.Paint += new System.Windows.Forms.PaintEventHandler(this.ProfitGraphBox_Paint);

		}
		#endregion

		private void ProfitGraphBox_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
		{
			if(profitList == null || profitList.Count <= 1)
				return;

			// 最大値と最小値を計算
			int count = profitList.Count;
			float maxY = float.MinValue;
			float minY = float.MaxValue;
			for(int i = 0; i < count; i++)
			{
				Profit profit = profitList[i];
				if(maxY < profit.BookProfit)
					maxY = profit.BookProfit;
				if(maxY < profit.MarketProfit)
					maxY = profit.MarketProfit;
				if(minY > profit.BookProfit)
					minY = profit.BookProfit;
				if(minY > profit.MarketProfit)
					minY = profit.MarketProfit;
			}
			if(maxY == minY)
			{
				maxY += 1;
				minY -= 1;
			}

			Brush brush = new SolidBrush(this.ForeColor);
			Pen pen = new Pen(this.ForeColor);
			Color dotColor = Color.FromArgb(
				(this.BackColor.A + this.ForeColor.A)/2,
				(this.BackColor.R + this.ForeColor.R)/2,
				(this.BackColor.G + this.ForeColor.G)/2,
				(this.BackColor.B + this.ForeColor.B)/2);
			Pen dotPen = new Pen(dotColor);
			dotPen.DashStyle = DashStyle.Dot;
			Pen bookPen = new Pen(Color.Red);
			Pen marketPen = new Pen(Color.Green);
			Rectangle chartRect = this.ClientRectangle;
			Graphics g = e.Graphics;
			float rx = (float)chartRect.Width/(count - 1);
			float ry = (float)chartRect.Height/(maxY - minY);

			// 縦軸の値の描画
			long band = (long)((maxY - minY)/6);
			long a = 1;
			while(true)
			{
				if(band < 10*a)
				{
					for(long b = a; b <= 10*a; b += a)
						if(b >= band)
						{
							band = b;
							break;
						}
					break;
				}
				a *= 10;
			}
			long m = 0;
			while(m - band > minY)
				m -= band;
			while(m < maxY)
			{
				float y = chartRect.Bottom - ry*(m - minY);
				g.DrawLine(dotPen, chartRect.Left, y, chartRect.Right, y);
				SizeF sizeF = g.MeasureString(m.ToString("C"), this.Font);
				g.DrawString(m.ToString("C"), this.Font, brush, chartRect.Left, y - sizeF.Height);
				m += band;
			}

			// 曲線の描画
			for(int i = 1; i < count; i++)
			{
				Profit p1 = profitList[i - 1];
				Profit p2 = profitList[i];
				float x1 = rx*(i - 1);
				float x2 = rx*i;
				float y1 = chartRect.Bottom - ry*(p1.MarketProfit - minY);
				float y2 = chartRect.Bottom - ry*(p2.MarketProfit - minY);
				g.DrawLine(marketPen, x1, y1, x2, y2);
				y1 = chartRect.Bottom - ry*(p1.BookProfit - minY);
				y2 = chartRect.Bottom - ry*(p2.BookProfit - minY);
				g.DrawLine(bookPen, x1, y1, x2, y2);
			}

			// 指標名の描画
			string text = "時価";
			Color color = Color.Green;
			SizeF size = g.MeasureString(text, this.Font);
			int x = (int)(chartRect.Right - size.Width - 10);
			int y0 = (int)(chartRect.Bottom - size.Height - 10);
			Rectangle rect = new Rectangle(x, y0, (int)size.Height, (int)size.Height);
			g.FillRectangle(new SolidBrush(color), rect);
			g.DrawRectangle(pen, rect);
			g.DrawString(text, this.Font, brush, rect.Right, rect.Top);
			text = "簿価";
			color = Color.Red;
			size = g.MeasureString(text, this.Font);
			x = (int)(rect.Left - size.Width - 10);
			rect = new Rectangle(x, y0, (int)size.Height, (int)size.Height);
			g.FillRectangle(new SolidBrush(color), rect);
			g.DrawRectangle(pen, rect);
			g.DrawString(text, this.Font, brush, rect.Right, rect.Top);
		}

		/// <summary>
		/// 描画対象となる利益のリストを取得または設定します。
		/// </summary>
		public ProfitList ProfitList
		{
			get { return profitList; }
			set
			{
				profitList = value;
				this.Invalidate();
			}
		}
	}
}
