import { autoinject } from 'aurelia-framework';
import { Config } from '../config';
import moment, { Moment } from 'moment';

@autoinject
export class DateUtils {
    constructor(public config: Config) { }

    format(date: Date | Moment, format: string): string {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.format(format);
    }

    toDate(date: Moment | string): Date {
        if (date == null) {
            return null
        }
        if (isString(date)) {
            date = moment(date);
        }
        return date.toDate();
    }

    getNumOfWeek(date: Date | Moment, locale: string = null): number {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        if (locale == null) {
            locale = this.config.globalConfig.defaultLocale;
        }
        return date.locale(locale).week();
    }

    //#region Is...
    isValid(date: Date | Moment): boolean {
        if (isDate(date)) {
            date = moment(date);
        }
        return date?.isValid();
    }
    isBefore(date: Date | Moment, dateToCompare: Date | Moment): boolean {
        if (date == null || dateToCompare == null) {
            return false
        }
        if (isDate(date)) {
            date = moment(date);
        }
        if (isDate(dateToCompare)) {
            dateToCompare = moment(dateToCompare);
        }
        return date.isBefore(dateToCompare);
    }
    isBeforeYear(date: Date | Moment, dateToCompare: Date | Moment): boolean {
        if (date == null || dateToCompare == null) {
            return false
        }
        if (isDate(date)) {
            date = moment(date);
        }
        if (isDate(dateToCompare)) {
            dateToCompare = moment(dateToCompare);
        }
        return date.get("year") < dateToCompare.get("year");
    }
    isAfter(date: Date | Moment, dateToCompare: Date | Moment): boolean {
        if (date == null || dateToCompare == null) {
            return false
        }
        if (isDate(date)) {
            date = moment(date);
        }
        if (isDate(dateToCompare)) {
            dateToCompare = moment(dateToCompare);
        }
        return date.isAfter(dateToCompare);
    }
    isAfterYear(date: Date | Moment, dateToCompare: Date | Moment): boolean {
        if (date == null || dateToCompare == null) {
            return false
        }
        if (isDate(date)) {
            date = moment(date);
        }
        if (isDate(dateToCompare)) {
            dateToCompare = moment(dateToCompare);
        }
        return date.get("year") > dateToCompare.get("year");
    }

    isSame(date: Date | Moment, dateToCompare: Date | Moment): boolean {
        if (date == null || dateToCompare == null) {
            return false
        }
        if (isDate(date)) {
            date = moment(date);
        }
        if (isDate(dateToCompare)) {
            dateToCompare = moment(dateToCompare);
        }
        return date.isSame(dateToCompare);
    }

    isSameOrAfter(date: Date | Moment, dateToCompare: Date | Moment): boolean {
        if (date == null || dateToCompare == null) {
            return false
        }
        if (isDate(date)) {
            date = moment(date);
        }
        if (isDate(dateToCompare)) {
            dateToCompare = moment(dateToCompare);
        }
        return date.isSameOrAfter(dateToCompare);
    }

    isSameOrBefore(date: Date | Moment, dateToCompare: Date | Moment): boolean {
        if (date == null || dateToCompare == null) {
            return false
        }
        if (isDate(date)) {
            date = moment(date);
        }
        if (isDate(dateToCompare)) {
            dateToCompare = moment(dateToCompare);
        }
        return date.isSameOrBefore(dateToCompare);
    }

    isSameDay(date: Date | Moment, dateToCompare: Date | Moment): boolean {
        if (date == null || dateToCompare == null) {
            return false
        }
        if (isDate(date)) {
            date = moment(date);
        }
        if (isDate(dateToCompare)) {
            dateToCompare = moment(dateToCompare);
        }
        return date.isSame(dateToCompare, "day");
    }
    isSameMonth(date: Date | Moment, dateToCompare: Date | Moment): boolean {
        if (date == null || dateToCompare == null) {
            return false
        }
        if (isDate(date)) {
            date = moment(date);
        }
        if (isDate(dateToCompare)) {
            dateToCompare = moment(dateToCompare);
        }
        return date.isSame(dateToCompare, "month");
    }
    isSameYear(date: Date | Moment, dateToCompare: Date | Moment): boolean {
        if (date == null || dateToCompare == null) {
            return false
        }
        if (isDate(date)) {
            date = moment(date);
        }
        if (isDate(dateToCompare)) {
            dateToCompare = moment(dateToCompare);
        }
        return date.isSame(dateToCompare, "year");
    }
    isWeekend(date: Date | Moment): boolean {
        if (isDate(date)) {
            date = moment(date);
        }
        return date.isoWeekday() == 6 || date.isoWeekday() == 7;
    }
    isStartOfMonth(date: Date | Moment): boolean {
        if (date == null) {
            return false;
        }
        let startOfMonth: Date | Moment = this.getStartOfMonth(date);
        if (isDate(startOfMonth)) {
            startOfMonth = moment(startOfMonth);
        }
        return startOfMonth.isSame(date, "day");
    }
    //#endregion

    //#region Add
    addHours(date: Date | Moment, nbHours: number): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.add(nbHours, "hour").toDate();
    }

    addDays(date: Date | Moment, nbDays: number): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.add(nbDays, "day").toDate();
    }

    addMonths(date: Date | Moment, nbMonths: number): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.add(nbMonths, "month").toDate();
    }

    addWeeks(date: Date | Moment, nbWeeks: number): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.add(nbWeeks, "week").toDate();
    }

    addYears(date: Date | Moment, nbYears: number): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.add(nbYears, "year").toDate();
    }
    //#endregion

    //#region subtract
    subtractHours(date: Date | Moment, nbHours: number): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.subtract(nbHours, "hour").toDate();
    }
    subtractDays(date: Date | Moment, nbDays: number): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.subtract(nbDays, "day").toDate();
    }

    subtractMonths(date: Date | Moment, nbMonths: number): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.subtract(nbMonths, "month").toDate();
    }

    subtractYears(date: Date | Moment, nbYears: number): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.subtract(nbYears, "year").toDate();
    }
    //#endregion

    //#region startOf
    getStartOfMinute(date: Date | Moment): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.startOf("minute").toDate();
    }
    getStartOfDay(date: Date | Moment): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.startOf("day").toDate();
    }
    getStartOfWeek(date: Date | Moment): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.startOf("isoWeek").toDate();
    }
    getStartOfMonth(date: Date | Moment): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.startOf("month").toDate();
    }
    getStartOfYear(date: Date | Moment): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.startOf("year").toDate();
    }
    getStartOfDecade(date: Date | Moment): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        date = date.startOf("year");
        return date.subtract(parseInt(date.get("year").toString().substring(3)), "year").toDate();
    }
    //#endregion

    //#region endOf
    getEndOfMinute(date: Date | Moment): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.endOf("minute").toDate();
    }
    getEndOfDay(date: Date | Moment): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.endOf("day").toDate();
    }
    getEndOfWeek(date: Date | Moment): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.endOf("isoWeek").toDate();
    }
    getEndOfMonth(date: Date | Moment): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.endOf("month").toDate();
    }
    getEndOfYear(date: Date | Moment): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.endOf("year").toDate();
    }
    getEndOfDecade(date: Date | Moment): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        date = date.endOf("year");
        return date.add(9 - parseInt(date.get("year").toString().substring(3)), "year").toDate();
    }
    //#endregion

    //#region set
    setMonths(date: Date | Moment, nbMonths: number): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.set("month", nbMonths).toDate();
    }
    setHours(date: Date | Moment, nbHours: number): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.set("hour", nbHours).toDate();
    }
    setMinutes(date: Date | Moment, nbMinutes: number): Date {
        if (date == null) {
            return null
        }
        if (isDate(date)) {
            date = moment(date);
        }
        return date.set("minute", nbMinutes).toDate();
    }
    //#endregion
}