using System;
using NUnit.Framework;

namespace Orciid.Core.Util
{
	/// <summary>
	/// Test class
	/// </summary>
	/// <remarks>
	/// Test cases
	/// </remarks>
	[TestFixture]
	public class TestScheduler
	{
		/// <summary>
		/// Test
		/// </summary>
        /// <remarks>
        /// Test
        /// </remarks>
		[Test]
		public void TestSimpleSchedule()
		{
			// every hour on the hour
			Scheduler.Rule rule = new Scheduler.Rule(
				Scheduler.Weekdays.All, 
				new DateTime(1, 1, 1, 0, 0, 0),
				TimeSpan.FromHours(24),
				TimeSpan.FromHours(1));

			Scheduler scheduler = new Scheduler(rule);

			DateTime next = scheduler.GetNextTime(new DateTime(2006, 11, 25, 11, 53, 23));

			Assert.AreEqual(2006, next.Year);
			Assert.AreEqual(11, next.Month);
			Assert.AreEqual(25, next.Day);
			Assert.AreEqual(12, next.Hour);
			Assert.AreEqual(0, next.Minute);
			Assert.AreEqual(0, next.Second);
		}

        /// <summary>
        /// Test
        /// </summary>
        /// <remarks>
        /// Test
        /// </remarks>
		[Test]
		public void TestWeekdaySchedule()
		{
			// every hour on the hour on Mondays after 7 am only
			Scheduler.Rule rule = new Scheduler.Rule(
				Scheduler.Weekdays.Monday, 
				new DateTime(1, 1, 1, 7, 0, 0),
				TimeSpan.FromHours(24),
				TimeSpan.FromHours(1));

			Scheduler scheduler = new Scheduler(rule);

			DateTime next = scheduler.GetNextTime(new DateTime(2006, 11, 25, 11, 53, 23));

			Assert.AreEqual(2006, next.Year);
			Assert.AreEqual(11, next.Month);
			Assert.AreEqual(27, next.Day);
			Assert.AreEqual(7, next.Hour);
			Assert.AreEqual(0, next.Minute);
			Assert.AreEqual(0, next.Second);
		}

        /// <summary>
        /// Test
        /// </summary>
        /// <remarks>
        /// Test
        /// </remarks>
		[Test]
		public void TestDayWrap()
		{
			// every 2 hours on Mondays, Wednesdays between 7:30 am and noon only
			Scheduler.Rule rule = new Scheduler.Rule(
				Scheduler.Weekdays.Monday | Scheduler.Weekdays.Wednesday, 
				new DateTime(1, 1, 1, 7, 30, 0),
				TimeSpan.FromHours(4.5),
				TimeSpan.FromHours(2));

			Scheduler scheduler = new Scheduler(rule);

			DateTime next = scheduler.GetNextTime(new DateTime(2006, 11, 27, 11, 53, 23));

			Assert.AreEqual(2006, next.Year);
			Assert.AreEqual(11, next.Month);
			Assert.AreEqual(29, next.Day);
			Assert.AreEqual(7, next.Hour);
			Assert.AreEqual(30, next.Minute);
			Assert.AreEqual(0, next.Second);

			next = scheduler.GetNextTime(next);
			Assert.AreEqual(2006, next.Year);
			Assert.AreEqual(11, next.Month);
			Assert.AreEqual(29, next.Day);
			Assert.AreEqual(9, next.Hour);
			Assert.AreEqual(30, next.Minute);
			Assert.AreEqual(0, next.Second);

			next = scheduler.GetNextTime(next);
			Assert.AreEqual(2006, next.Year);
			Assert.AreEqual(11, next.Month);
			Assert.AreEqual(29, next.Day);
			Assert.AreEqual(11, next.Hour);
			Assert.AreEqual(30, next.Minute);
			Assert.AreEqual(0, next.Second);

			next = scheduler.GetNextTime(next);
			Assert.AreEqual(2006, next.Year);
			Assert.AreEqual(12, next.Month);
			Assert.AreEqual(4, next.Day);
			Assert.AreEqual(7, next.Hour);
			Assert.AreEqual(30, next.Minute);
			Assert.AreEqual(0, next.Second);
		}

        /// <summary>
        /// Test
        /// </summary>
        /// <remarks>
        /// Test
        /// </remarks>
		[Test]
		public void TestMultipleRules()
		{
			// every 2 hours on Mondays, Wednesdays between 7:30 am and noon only
			Scheduler.Rule rule1 = new Scheduler.Rule(
				Scheduler.Weekdays.Monday | Scheduler.Weekdays.Wednesday, 
				new DateTime(1, 1, 1, 7, 30, 0),
				TimeSpan.FromHours(4.5),
				TimeSpan.FromHours(2));
			// every hour on Tuesdays between 2:30 pm and 3:45 pm
			Scheduler.Rule rule2 = new Scheduler.Rule(
				Scheduler.Weekdays.Tuesday, 
				new DateTime(1, 1, 1, 14, 30, 0),
				TimeSpan.FromHours(1.75),
				TimeSpan.FromHours(1));
			// once at 6 am on Tuesday
			Scheduler.Rule rule3 = new Scheduler.Rule(
				Scheduler.Weekdays.Tuesday, 
				new DateTime(1, 1, 1, 6, 0, 0),
				TimeSpan.FromHours(0),
				TimeSpan.Zero);

			Scheduler scheduler = new Scheduler(rule1, rule2, rule3);

			DateTime next = scheduler.GetNextTime(new DateTime(2006, 11, 27, 10, 53, 23));

			Assert.AreEqual(2006, next.Year);
			Assert.AreEqual(11, next.Month);
			Assert.AreEqual(27, next.Day);
			Assert.AreEqual(11, next.Hour);
			Assert.AreEqual(30, next.Minute);
			Assert.AreEqual(0, next.Second);
			
			next = scheduler.GetNextTime(next);
			Assert.AreEqual(2006, next.Year);
			Assert.AreEqual(11, next.Month);
			Assert.AreEqual(28, next.Day);
			Assert.AreEqual(6, next.Hour);
			Assert.AreEqual(0, next.Minute);
			Assert.AreEqual(0, next.Second);

			next = scheduler.GetNextTime(next);
			Assert.AreEqual(2006, next.Year);
			Assert.AreEqual(11, next.Month);
			Assert.AreEqual(28, next.Day);
			Assert.AreEqual(14, next.Hour);
			Assert.AreEqual(30, next.Minute);
			Assert.AreEqual(0, next.Second);

			next = scheduler.GetNextTime(next);
			Assert.AreEqual(2006, next.Year);
			Assert.AreEqual(11, next.Month);
			Assert.AreEqual(28, next.Day);
			Assert.AreEqual(15, next.Hour);
			Assert.AreEqual(30, next.Minute);
			Assert.AreEqual(0, next.Second);

			next = scheduler.GetNextTime(next);
			Assert.AreEqual(2006, next.Year);
			Assert.AreEqual(11, next.Month);
			Assert.AreEqual(29, next.Day);
			Assert.AreEqual(7, next.Hour);
			Assert.AreEqual(30, next.Minute);
			Assert.AreEqual(0, next.Second);
		}
	}
}
