export class DateUtils {
    public static getIntervalDays(from: Date, to: Date, daysOfYear: DaysOfYear = DaysOfYear.ThirtyDaysPerMonth, countEndDate: boolean = false): number {
        let isNegative = false;
        if (from > to) {
            isNegative = true;
            let temp = new Date(to);
            to = from;
            from = temp;
        }

        var days = 0;
        if (from && to) {
            //Get date without time
            from = new Date(from.getFullYear(), from.getMonth(), from.getDate());
            to = new Date(to.getFullYear(), to.getMonth(), to.getDate());
            var differenceTime = to.getTime() - from.getTime();
            if (differenceTime > 0) {
                if (daysOfYear == DaysOfYear.ThirtyDaysPerMonth) {
                    var fromYear = from.getFullYear();
                    var toYear = to.getFullYear();
                    var fromMonth = from.getMonth() + 1;
                    var toMonth = to.getMonth() + 1;

                    var fromDays = from.getDate() > 30 ? 30 : from.getDate();
                    var toDays = to.getDate();

                    days += 30 - fromDays;
                    days += toDays;
                    //calculate full 12 months years
                    if (toYear > (fromYear + 1)) {
                        days += (toYear - fromYear - 1) * 12 * 30;
                    }

                    //if it's two different years, calculate the interval months
                    if (toYear > fromYear) {
                        days += (12 - fromMonth) * 30;
                        days += (toMonth - 1) * 30;
                    }
                    else {
                        //same year
                        days += (toMonth - fromMonth - 1) * 30
                    }
                }
                else {
                    // To calculate the no. of days between two dates
                    days = Math.round(differenceTime / (1000 * 3600 * 24));
                }
            }
        }

        return (days + (countEndDate ? 1 : 0)) * (isNegative ? -1 : 1);
    }

    public static addDays(date: Date, days: number): Date {
        if (date) {
            var result = new Date(date);
            result.setDate(result.getDate() + days);
            return result;
        }
        return date;
    }

    public static format(date: Date, format: string, nullFormat: string = ''): string {
        if (date) {
            var z = {
                M: date.getMonth() + 1,
                d: date.getDate(),
                H: date.getHours(),
                h: (date.getHours() == 0 ? date.getHours() + 12 : date.getHours() > 12 ? date.getHours() - 12 : date.getHours()),
                m: date.getMinutes(),
                s: date.getSeconds(),
                a: (date.getHours() > 11 ? 'PM' : 'AM')
            };
            format = format.replace(/(M+|d+|H+|h+|m+|s+|a+)/g, function (v) {
                return ((v.length > 1 ? "0" : "") + z[v.slice(-1)]).slice(-2);
            });

            return format.replace(/(y+)/g, function (v) {
                return date.getFullYear().toString().slice(-v.length)
            });
        }
        return nullFormat;
    }
    public static isValidDate(d): boolean {
        return d instanceof Date && d.getTime() == d.getTime();
    }
    public static parse(value): Date {
        if (value) {
            value = new Date(value);
        }
        return value
    }

    public static getToday(endOfDay: boolean = false): Date {
        let value = new Date();
        if (!endOfDay) {
            value.setHours(0, 0, 0, 0);
        }
        else {
            value.setHours(23, 59, 59, 999);
        }
        return value
    }

    public static getBeginOfDate(value): Date {
        if (value) {
            value = new Date(value);
            value.setHours(0, 0, 0, 0);
        }
        return value
    }

    public static getEndOfDate(value): Date {
        if (value) {
            value = new Date(value);
            value.setHours(23, 59, 59, 999);
        }
        return value
    }
    public static getEndOfMonth(value): Date {
        if (value) {
            return new Date(value.getFullYear(), value.getMonth() + 1, 0)
        }
        return value;
    }

    public static isSameDate(date: Date, comparison: Date): boolean {
        if (!date || !comparison) return (!date && !comparison);
        date = this.parse(date);
        comparison = this.parse(comparison);
        return date.getFullYear() == comparison.getFullYear() && date.getMonth() == comparison.getMonth() && date.getDate() == comparison.getDate();
    }

    public static changeTimezone(date, ianatz) {
        // suppose the date is 12:00 UTC
        var invdate = new Date(date.toLocaleString('en-US', {
            timeZone: ianatz
        }));

        // then invdate will be 07:00 in Toronto
        // and the diff is 5 hours
        var diff = date.getTime() - invdate.getTime();

        // so 12:00 in Toronto is 17:00 UTC
        return new Date(date.getTime() + diff);
    }

    public static changeTimezoneByOffset(date, tzOffset) {
        let time = date.getTime();
        return new Date(time - (tzOffset * 60000));
    }

    public static getTimeStamp() {
        var now = new Date();
        return ((now.getMonth() + 1) + '/' + (now.getDate()) + '/' + now.getFullYear() + " " + now.getHours() + ':'
            + ((now.getMinutes() < 10) ? ("0" + now.getMinutes()) : (now.getMinutes())) + ':' + ((now.getSeconds() < 10) ? ("0" + now
                .getSeconds()) : (now.getSeconds())));
    }


    public static getDatesBetween(startDate: Date, endDate: Date): Date[] {
        startDate = this.getBeginOfDate(startDate);
        endDate = this.getBeginOfDate(endDate);
        let result = [startDate];
        if (startDate < endDate) {
            let tempDate = new Date(startDate);
            while (tempDate < endDate) {
                tempDate = this.addDays(tempDate, 1);
                result.push(tempDate);
            }
        }
        return result;
    }
}

export enum DaysOfYear {
    ThirtyDaysPerMonth = 360,
    FullYearDays = 365
}


export enum DatePeriod {
    Daily,
    Weekly,
    Monthly,
    Quarterly,
    SemiAnnually,
    Annually,
    Period,
}