import { isNullOrUndefined } from 'util';

export abstract class DateAdapter<TDate> {
  abstract getYear(date: TDate): number;

  abstract getMonth(date: TDate): number;

  abstract getDate(date: TDate): number;

  abstract getYearName(date: TDate): string;

  abstract getMonthName(date: TDate): string;

  abstract getDateName(date: TDate): string;

  abstract addCalendarMonths(date: TDate, months: number): TDate;

  abstract addCalendarDays(date: TDate, days: number): TDate;

  abstract createDate(year: number, month: number, date: number): TDate;

  abstract today(): TDate;

  abstract isValid(date: TDate): boolean;

  abstract getFirstDateOfWeek(date: TDate): TDate;

  abstract getLastDateOfWeek(date: TDate): TDate;

  abstract getFirstDateOfMonth(date: TDate): TDate;

  abstract getLastDateOfMonth(date: TDate): TDate;

  abstract getDifferenceInDays(first: TDate, second: TDate): number;

  abstract getDayOfWeek(date: TDate): number;

  compareDate(first: TDate, second: TDate) {
    if (isNullOrUndefined(first) || isNullOrUndefined(second)) {
      return null;
    }

    return (
      this.getYear(first) - this.getYear(second) ||
      this.getMonth(first) - this.getMonth(second) ||
      this.getDate(first) - this.getDate(second)
    );
  }

  compareYearAndMonth(first: TDate, second: TDate) {
    if (isNullOrUndefined(first) || isNullOrUndefined(second)) {
      return null;
    }
    return this.getYear(first) - this.getYear(second) || this.getMonth(first) - this.getMonth(second);
  }
}
