import { TestBed } from '@angular/core/testing';
import { DateAdapter } from './data.adapter';

describe('DateAdapter', () => {
  let adapter: DateAdapter;

  beforeEach(() => {
    TestBed.configureTestingModule({});

    adapter = TestBed.inject(DateAdapter);
  });

  it('should create the service', () => {
    expect(adapter instanceof DateAdapter).toBeTruthy();
  });

  describe('#getDatesAndCalendarWeeksForMonth', () => {
    it('should return the calendar weeks and dates for 01.2019', () => {
      const weeks = adapter.getDatesAndCalendarWeeksForMonth(2019, 1);

      // woche 1
      const datesWeek1 = [
        adapter.parseDate(2018, 12, 31),
        adapter.parseDate(2019, 1, 1),
        adapter.parseDate(2019, 1, 2),
        adapter.parseDate(2019, 1, 3),
        adapter.parseDate(2019, 1, 4),
        adapter.parseDate(2019, 1, 5),
        adapter.parseDate(2019, 1, 6),
      ];
      const week1 = weeks.find((w) => w.week === 1);
      expect(week1).toBeDefined();

      for (let index = 0; index < datesWeek1.length; index++) {
        expect(week1.dates[index]).toEqual(datesWeek1[index]);
      }

      // woche 2
      const datesWeek2 = [
        adapter.parseDate(2019, 1, 7),
        adapter.parseDate(2019, 1, 8),
        adapter.parseDate(2019, 1, 9),
        adapter.parseDate(2019, 1, 10),
        adapter.parseDate(2019, 1, 11),
        adapter.parseDate(2019, 1, 12),
        adapter.parseDate(2019, 1, 13),
      ];
      const week2 = weeks.find((w) => w.week === 2);
      expect(week2).toBeDefined();

      for (let index = 0; index < datesWeek2.length; index++) {
        expect(week2.dates[index]).toEqual(datesWeek2[index]);
      }

      // woche 3
      const datesWeek3 = [
        adapter.parseDate(2019, 1, 14),
        adapter.parseDate(2019, 1, 15),
        adapter.parseDate(2019, 1, 16),
        adapter.parseDate(2019, 1, 17),
        adapter.parseDate(2019, 1, 18),
        adapter.parseDate(2019, 1, 19),
        adapter.parseDate(2019, 1, 20),
      ];
      const week3 = weeks.find((w) => w.week === 3);
      expect(week3).toBeDefined();

      for (let index = 0; index < datesWeek3.length; index++) {
        expect(week3.dates[index]).toEqual(datesWeek3[index]);
      }

      // woche 4
      const datesWeek4 = [
        adapter.parseDate(2019, 1, 21),
        adapter.parseDate(2019, 1, 22),
        adapter.parseDate(2019, 1, 23),
        adapter.parseDate(2019, 1, 24),
        adapter.parseDate(2019, 1, 25),
        adapter.parseDate(2019, 1, 26),
        adapter.parseDate(2019, 1, 27),
      ];
      const week4 = weeks.find((w) => w.week === 4);
      expect(week4).toBeDefined();

      for (let index = 0; index < datesWeek4.length; index++) {
        expect(week4.dates[index]).toEqual(datesWeek4[index]);
      }

      // woche 5
      const datesWeek5 = [
        adapter.parseDate(2019, 1, 28),
        adapter.parseDate(2019, 1, 29),
        adapter.parseDate(2019, 1, 30),
        adapter.parseDate(2019, 1, 31),
        adapter.parseDate(2019, 2, 1),
        adapter.parseDate(2019, 2, 2),
        adapter.parseDate(2019, 2, 3),
      ];
      const week5 = weeks.find((w) => w.week === 5);
      expect(week5).toBeDefined();

      for (let index = 0; index < datesWeek5.length; index++) {
        expect(week5.dates[index]).toEqual(datesWeek5[index]);
      }
    });

    it('should return the calendar weeks and dates for 12.2019', () => {
      const weeks = adapter.getDatesAndCalendarWeeksForMonth(2019, 12);

      // erste woche
      const datesWeek1 = [
        adapter.parseDate(2019, 11, 25),
        adapter.parseDate(2019, 11, 26),
        adapter.parseDate(2019, 11, 27),
        adapter.parseDate(2019, 11, 28),
        adapter.parseDate(2019, 11, 29),
        adapter.parseDate(2019, 11, 30),
        adapter.parseDate(2019, 12, 1),
      ];
      const week1 = weeks.find((w) => w.week === 48);
      expect(week1).toBeDefined();

      for (let index = 0; index < datesWeek1.length; index++) {
        expect(week1.dates[index]).toEqual(datesWeek1[index]);
      }

      // letzte woche
      const datesWeek2 = [
        adapter.parseDate(2019, 12, 30),
        adapter.parseDate(2019, 12, 31),
        adapter.parseDate(2020, 1, 1),
        adapter.parseDate(2020, 1, 2),
        adapter.parseDate(2020, 1, 3),
        adapter.parseDate(2020, 1, 4),
        adapter.parseDate(2020, 1, 5),
      ];
      const week2 = weeks.find((w) => w.week === 1);
      expect(week2).toBeDefined();

      for (let index = 0; index < datesWeek2.length; index++) {
        expect(week2.dates[index]).toEqual(datesWeek2[index]);
      }
    });

    it('should return the calendar weeks and dates for 06.2020', () => {
      const weeks = adapter.getDatesAndCalendarWeeksForMonth(2020, 6);

      // erste woche
      const datesWeek1 = [
        adapter.parseDate(2020, 6, 1),
        adapter.parseDate(2020, 6, 2),
        adapter.parseDate(2020, 6, 3),
        adapter.parseDate(2020, 6, 4),
        adapter.parseDate(2020, 6, 5),
        adapter.parseDate(2020, 6, 6),
        adapter.parseDate(2020, 6, 7),
      ];
      const week1 = weeks.find((w) => w.week === 23);
      expect(week1).toBeDefined();

      for (let index = 0; index < datesWeek1.length; index++) {
        expect(week1.dates[index]).toEqual(datesWeek1[index]);
      }

      // letzte woche
      const datesWeek2 = [
        adapter.parseDate(2020, 6, 29),
        adapter.parseDate(2020, 6, 30),
        adapter.parseDate(2020, 7, 1),
        adapter.parseDate(2020, 7, 2),
        adapter.parseDate(2020, 7, 3),
        adapter.parseDate(2020, 7, 4),
        adapter.parseDate(2020, 7, 5),
      ];
      const week2 = weeks.find((w) => w.week === 27);
      expect(week2).toBeDefined();

      for (let index = 0; index < datesWeek2.length; index++) {
        expect(week2.dates[index]).toEqual(datesWeek2[index]);
      }
    });
  });

  describe('#getDatesForCalendarWeek', () => {
    it('should return the dates for calendar week 1', () => {
      const dates = adapter.getDatesForCalendarWeek(2019, 1);

      const datesWeek = [
        adapter.parseDate(2018, 12, 31),
        adapter.parseDate(2019, 1, 1),
        adapter.parseDate(2019, 1, 2),
        adapter.parseDate(2019, 1, 3),
        adapter.parseDate(2019, 1, 4),
        adapter.parseDate(2019, 1, 5),
        adapter.parseDate(2019, 1, 6),
      ];

      for (let index = 0; index < datesWeek.length; index++) {
        expect(dates[index]).toEqual(datesWeek[index]);
      }
    });

    it('should return the dates for calendar week 46', () => {
      const dates = adapter.getDatesForCalendarWeek(2019, 46);

      const datesWeek = [
        adapter.parseDate(2019, 11, 11),
        adapter.parseDate(2019, 11, 12),
        adapter.parseDate(2019, 11, 13),
        adapter.parseDate(2019, 11, 14),
        adapter.parseDate(2019, 11, 15),
        adapter.parseDate(2019, 11, 16),
        adapter.parseDate(2019, 11, 17),
      ];

      for (let index = 0; index < datesWeek.length; index++) {
        expect(dates[index]).toEqual(datesWeek[index]);
      }
    });

    it('should return the dates for calendar week 52', () => {
      const dates = adapter.getDatesForCalendarWeek(2019, 52);

      const datesWeek = [
        adapter.parseDate(2019, 12, 23),
        adapter.parseDate(2019, 12, 24),
        adapter.parseDate(2019, 12, 25),
        adapter.parseDate(2019, 12, 26),
        adapter.parseDate(2019, 12, 27),
        adapter.parseDate(2019, 12, 28),
        adapter.parseDate(2019, 12, 29),
      ];

      for (let index = 0; index < datesWeek.length; index++) {
        expect(dates[index]).toEqual(datesWeek[index]);
      }
    });
  });

  describe('#getCalendarWeek', () => {
    it('should return the calendar week for 14.06.2019', () => {
      const week = adapter.getCalendarWeek(2019, 6, 14);

      expect(week).toEqual(24);
    });

    it('should return the calendar week for 4.02.2019', () => {
      const week = adapter.getCalendarWeek(2019, 2, 4);
      expect(week).toEqual(6);
    });

    it('should return the calendar week for 19.09.2019', () => {
      const week = adapter.getCalendarWeek(2019, 9, 19);
      expect(week).toEqual(38);
    });
  });

  describe('#getCalendarWeeksForMonth', () => {
    it('should return the calendar weeks for 02.2020', () => {
      const calendarWeeks = adapter.getCalendarWeeksForMonth(2020, 2);

      expect(calendarWeeks).toEqual([5, 6, 7, 8, 9]);
    });

    it('should return the calendar weeks for 12.2020', () => {
      const calendarWeeks = adapter.getCalendarWeeksForMonth(2020, 12);

      expect(calendarWeeks).toEqual([49, 50, 51, 52, 1]);
    });

    it('should return the calendar weeks for 7.2020', () => {
      const calendarWeeks = adapter.getCalendarWeeksForMonth(2020, 7);

      expect(calendarWeeks).toEqual([27, 28, 29, 30, 31]);
    });
  });

  describe('#getMonthForCalendarWeek', () => {
    it('should return the month for week 1 in year 2020', () => {
      const month = adapter.getMonthForCalendarWeek(2020, 1);
      expect(month).toEqual(1);
    });
  });

  describe('#parseDate', () => {
    it('should return the parsed date for 15.02.2018', () => {
      expect(adapter.parseDate(2019, 2, 15)).toEqual(new Date(2019, 1, 15));
    });

    it('should return the parsed date for 02.06.2019', () => {
      expect(adapter.parseDate(2019, 6, 2)).toEqual(new Date(2019, 5, 2));
    });

    it('should return the parsed date for 23.12.2019', () => {
      expect(adapter.parseDate(2019, 12, 23)).toEqual(new Date(2019, 11, 23));
    });
  });

  describe('#getDate', () => {
    it('should return a date object for 04.06.2013', () => {
      expect(adapter.getDate(new Date(2013, 5, 4))).toEqual({
        year: 2013,
        month: 6,
        date: 4,
      });
    });

    it('should retrun a date object for 01.09.2017', () => {
      expect(adapter.getDate(new Date(2017, 8, 1))).toEqual({
        year: 2017,
        month: 9,
        date: 1,
      });
    });

    it('should retrun a date object for 23.11.2020', () => {
      expect(adapter.getDate(new Date(2020, 10, 23))).toEqual({
        year: 2020,
        month: 11,
        date: 23,
      });
    });
  });

  describe('#equals', () => {
    it('should be equal', () => {
      expect(adapter.equals(new Date(2019, 5, 12), new Date(2019, 5, 12, 12, 40)));
    });

    it('should not be equal', () => {
      expect(adapter.equals(new Date(2019, 6, 12), new Date(2019, 5, 12, 12, 40)));
    });
  });
});
