using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using System.IO.IsolatedStorage;

namespace Biorhythm
{
	public partial class MainPage : PhoneApplicationPage
	{
		DateTime myBirthday;

		public DateTime Birthday { get { return myBirthday; } set { myBirthday = value; } }
		
		public MainPage ()
		{
			InitializeComponent ();
		}

		/// <summary>
		/// 지정된 연도 사이의 총 윤년 계산
		/// </summary>
		/// <param name="startYear">시작 연도</param>
		/// <param name="endYear">종료 연도</param>
		/// <returns></returns>
		private int GetLeapYears ( int startYear, int endYear )
		{
			int leap = 0;
			for ( int i = startYear; i <= endYear; i++ )
				if ( DateTime.IsLeapYear ( i ) )
					leap++;
			return leap;
		}

		/// <summary>
		/// 나머지 일 수 계산
		/// </summary>
		/// <param name="startYear">시작일</param>
		/// <param name="endYear">종료일</param>
		/// <returns></returns>
		int GetRatingDays ( DateTime startYear, DateTime endYear )
		{
			return endYear.Subtract ( startYear ).Days;
		}

		/// <summary>
		/// 지난 달의 날짜 가져옴
		/// </summary>
		/// <returns>지날 달</returns>
		private int GetLastMonth ()
		{
			int T, n, a, alpha;
			DateTime lastMonth = DateTime.Today.AddMonths ( -1 );
			n = lastMonth.Year - myBirthday.Year;
			a = GetRatingDays ( myBirthday, lastMonth );
			alpha = GetLeapYears ( myBirthday.Year, lastMonth.Year );
			T = 365 * n + a + alpha;
			return T;
		}

		/// <summary>
		/// 오늘의 날짜 가져옴
		/// </summary>
		/// <returns>이번 달</returns>
		private int GetToday ()
		{
			int T, n, a, alpha;
			n = DateTime.Today.Year - myBirthday.Year;
			a = GetRatingDays ( myBirthday, DateTime.Today );
			alpha = GetLeapYears ( myBirthday.Year, DateTime.Today.Year );
			T = 365 * n + a + alpha;
			return T;
		}

		/// <summary>
		/// 다음 달의 날짜 가져옴
		/// </summary>
		/// <returns>다음 달</returns>
		private int GetNextMonth ()
		{
			int T, n, a, alpha;
			DateTime nextMonth = DateTime.Today.AddMonths ( 1 );
			n = nextMonth.Year - myBirthday.Year;
			a = GetRatingDays ( myBirthday, nextMonth );
			alpha = GetLeapYears ( myBirthday.Year, nextMonth.Year );
			T = 365 * n + a + alpha;
			return T;
		}

		/// <summary>
		/// 신체 바이오리듬 계산
		/// </summary>
		/// <param name="day">날짜</param>
		/// <returns>바이오리듬 지수</returns>
		private double CalculPhysical ( int day )
		{
			return ( Math.Sin ( day / 23.0 * 2 * Math.PI ) * 100 );
		}

		/// <summary>
		/// 감성 바이오리듬 계산
		/// </summary>
		/// <param name="day">날짜</param>
		/// <returns>바이오리듬 지수</returns>
		private double CalculEmotion ( int day )
		{
			return ( Math.Sin ( day / 28.0 * 2 * Math.PI ) * 100 );
		}

		/// <summary>
		/// 지성 바이오리듬 계산
		/// </summary>
		/// <param name="day">날짜</param>
		/// <returns>바이오리듬 지수</returns>
		private double CalculKnowledge ( int day )
		{
			return ( Math.Sin ( day / 33.0 * 2 * Math.PI ) * 100 );
		}

		/// <summary>
		/// 그래프 지정
		/// </summary>
		/// <param name="path">패스 컨트롤</param>
		/// <param name="color">색상</param>
		/// <param name="p1">지난 달의 바이오리듬 지수</param>
		/// <param name="p2">이번 달의 바이오리듬 지수</param>
		/// <param name="p3">다음 달의 바이오리듬 지수</param>
		private void SetGraph ( Path path, Color color, Point p1, Point p2, Point p3 )
		{
			GeometryGroup physicalPath = new GeometryGroup ();

			physicalPath.Children.Add ( new LineGeometry () { StartPoint = new Point ( 0, 0 ), EndPoint = new Point ( 1, 0 ) } );
			physicalPath.Children.Add ( new LineGeometry () { StartPoint = new Point ( 0.5, 100 ), EndPoint = new Point ( 0.5, -100 ) } );

			PathGeometry pg = new PathGeometry ();
			PathFigure figure = new PathFigure () { StartPoint = p1 };
			figure.Segments.Add ( new BezierSegment () { Point1 = p1, Point2 = p2, Point3 = p3 } );
			pg.Figures.Add ( figure );

			physicalPath.Children.Add ( pg );

			path.Data = physicalPath;
			path.Stroke = new SolidColorBrush ( color );
			path.Stretch = Stretch.Fill;
			path.StrokeThickness = 2;
		}

		private void PhoneApplicationPage_Loaded ( object sender, RoutedEventArgs e )
		{
			try
			{
				using ( IsolatedStorageFileStream fs = new IsolatedStorageFileStream ( "birthday.dat",
					System.IO.FileMode.Open, IsolatedStorageFile.GetUserStoreForApplication () ) )
				{
					System.IO.BinaryReader br = new System.IO.BinaryReader ( fs );
					myBirthday = DateTime.Parse ( br.ReadString () );
					br.Close ();
				}
			}
			catch { myBirthday = DateTime.Today; }

			txtBirth.Text = myBirthday.ToString ( "yyyy-MM-dd" );

			SetGraph ( path1, Color.FromArgb ( 255, 255, 0, 0 ),
				new Point ( 0, CalculPhysical ( GetLastMonth () ) * -1 ),
				new Point ( 0.5, CalculPhysical ( GetToday () ) * -1 ),
				new Point ( 1, CalculPhysical ( GetNextMonth () ) * -1 )
				);
			txt1.Text = String.Format ( "{0:0}", CalculPhysical ( GetToday () ) );

			SetGraph ( path2, Color.FromArgb ( 255, 0, 255, 0 ),
				new Point ( 0, CalculEmotion ( GetLastMonth () ) * -1 ),
				new Point ( 0.5, CalculEmotion ( GetToday () ) * -1 ),
				new Point ( 1, CalculEmotion ( GetNextMonth () ) * -1 )
				);
			txt2.Text = String.Format ( "{0:0}", CalculEmotion ( GetToday () ) );

			SetGraph ( path3, Color.FromArgb ( 255, 0, 0, 255 ),
				new Point ( 0, CalculKnowledge ( GetLastMonth () ) * -1 ),
				new Point ( 0.5, CalculKnowledge ( GetToday () ) * -1 ),
				new Point ( 1, CalculKnowledge ( GetNextMonth () ) * -1 )
				);
			txt3.Text = String.Format ( "{0:0}", CalculKnowledge ( GetToday () ) );
		}

		protected override void OnNavigatedTo ( System.Windows.Navigation.NavigationEventArgs e )
		{
			if ( e.NavigationMode == System.Windows.Navigation.NavigationMode.Back )
			{
				if ( PhoneApplicationService.Current.State.Count <= 0 ) return;

				myBirthday = ( DateTime ) PhoneApplicationService.Current.State [ "Birthday" ];

				using ( IsolatedStorageFileStream fs = new IsolatedStorageFileStream ( "birthday.dat",
					System.IO.FileMode.Create, IsolatedStorageFile.GetUserStoreForApplication () ) )
				{
					System.IO.BinaryWriter bw = new System.IO.BinaryWriter ( fs );
					bw.Write ( myBirthday.ToString () );
					bw.Close ();
				}

				txtBirth.Text = myBirthday.ToString ( "yyyy-MM-dd" );

				SetGraph ( path1, Color.FromArgb ( 255, 255, 0, 0 ),
					new Point ( 0, CalculPhysical ( GetLastMonth () ) * -1 ),
					new Point ( 0.5, CalculPhysical ( GetToday () ) * -1 ),
					new Point ( 1, CalculPhysical ( GetNextMonth () ) * -1 )
					);
				txt1.Text = String.Format ( "{0:0}", CalculPhysical ( GetToday () ) );

				SetGraph ( path2, Color.FromArgb ( 255, 0, 255, 0 ),
					new Point ( 0, CalculEmotion ( GetLastMonth () ) * -1 ),
					new Point ( 0.5, CalculEmotion ( GetToday () ) * -1 ),
					new Point ( 1, CalculEmotion ( GetNextMonth () ) * -1 )
					);
				txt2.Text = String.Format ( "{0:0}", CalculEmotion ( GetToday () ) );

				SetGraph ( path3, Color.FromArgb ( 255, 0, 0, 255 ),
					new Point ( 0, CalculKnowledge ( GetLastMonth () ) * -1 ),
					new Point ( 0.5, CalculKnowledge ( GetToday () ) * -1 ),
					new Point ( 1, CalculKnowledge ( GetNextMonth () ) * -1 )
					);
				txt3.Text = String.Format ( "{0:0}", CalculKnowledge ( GetToday () ) );
			}
			base.OnNavigatedTo ( e );
		}

		private void ApplicationBarMenuItem_Click ( object sender, EventArgs e )
		{
			if ( !PhoneApplicationService.Current.State.ContainsKey ( "Birthday" ) )
				PhoneApplicationService.Current.State.Add ( new KeyValuePair<string, object> ( "Birthday", myBirthday ) );
			else
				PhoneApplicationService.Current.State [ "Birthday" ] = myBirthday;
			NavigationService.Navigate ( new Uri ( "/SettingPage.xaml", UriKind.RelativeOrAbsolute ) );
		}
	}
}