﻿using System;
using NetChris.Scheduling.Holidays;
using Xunit;

namespace NetChris.Scheduling.Tests.Temporal.Holiday
{
    public class WesternGregorianEasterTests
    {
        [Fact]
        public void Test2009()
        {
            TestYear(2009, 4, 12);
        }

        [Fact]
        public void Test2010()
        {
            TestYear(2010, 4, 4);
        }

        [Fact]
        public void Test2011()
        {
            TestYear(2011, 4, 24);
        }

        [Fact]
        public void Test2012()
        {
            TestYear(2012, 4, 8);
        }

        [Fact]
        public void Test2013()
        {
            TestYear(2013, 3, 31);
        }

        [Fact]
        public void Test2014()
        {
            TestYear(2014, 4, 20);
        }

        [Fact]
        public void Test2015()
        {
            TestYear(2015, 4, 5);
        }

        [Fact]
        public void Test2016()
        {
            TestYear(2016, 3, 27);
        }

        [Fact]
        public void Test2017()
        {
            TestYear(2017, 4, 16);
        }

        [Fact]
        public void Test2018()
        {
            TestYear(2018, 4, 1);
        }

        [Fact]
        public void Test2019()
        {
            TestYear(2019, 4, 21);
        }

        [Fact]
        public void Test2020()
        {
            TestYear(2020, 4, 12);
        }

        [Fact]
        public void Test2021()
        {
            TestYear(2021, 4, 4);
        }

        [Fact]
        public void Test2022()
        {
            TestYear(2022, 4, 17);
        }

        [Fact]
        public void Test2023()
        {
            TestYear(2023, 4, 9);
        }

        [Fact]
        public void Test2024()
        {
            TestYear(2024, 3, 31);
        }

        [Fact]
        public void Test2025()
        {
            TestYear(2025, 4, 20);
        }

        [Fact]
        public void Test2026()
        {
            TestYear(2026, 4, 5);
        }

        [Fact]
        public void Test2027()
        {
            TestYear(2027, 3, 28);
        }

        [Fact]
        public void Test2028()
        {
            TestYear(2028, 4, 16);
        }

        [Fact]
        public void Test2029()
        {
            TestYear(2029, 4, 1);
        }

        [Fact]
        public void Test2030()
        {
            TestYear(2030, 4, 21);
        }

        [Fact]
        public void Test2031()
        {
            TestYear(2031, 4, 13);
        }

        [Fact]
        public void Test2032()
        {
            TestYear(2032, 3, 28);
        }

        [Fact]
        public void Test2033()
        {
            TestYear(2033, 4, 17);
        }

        [Fact]
        public void Test2034()
        {
            TestYear(2034, 4, 9);
        }

        [Fact]
        public void Test2035()
        {
            TestYear(2035, 3, 25);
        }

        [Fact]
        public void Test2036()
        {
            TestYear(2036, 4, 13);
        }

        [Fact]
        public void Test2037()
        {
            TestYear(2037, 4, 5);
        }

        [Fact]
        public void Test2038()
        {
            TestYear(2038, 4, 25);
        }

        [Fact]
        public void Test2039()
        {
            TestYear(2039, 4, 10);
        }

        [Fact]
        public void Test2049()
        {
            // This tests one corner case in the algorithm
            TestYear(2049, 4, 18);
        }

        [Fact]
        public void Test2076()
        {
            // This tests one corner case in the algorithm
            TestYear(2076, 4, 19);
        }

        // Tests a specific date, asserts that is it Easter, and then asserts that all other
        // days in the year are not Easter
        private static void TestYear(int year, int month, int day)
        {
            // Arrange
            var expression = new WesternGregorianEaster();
            DateTime easterCandidate = new DateTime(year, month, day);

            // Assert
            Assert.True(expression.Includes(easterCandidate), "Date is not Easter: " + easterCandidate);

            DateTime start = new DateTime(year, 1, 1);
            DateTime nextYear = new DateTime(year + 1, 1, 1);
            while (start.Date < nextYear.Date)
            {
                if (start.Date != easterCandidate.Date)
                {
                    Assert.False(expression.Includes(start),
                        "Date should not have been Easter: " + start);
                }
                start = start.AddDays(1.0);
            }
        }
    }
}
