import DatabaseProperty from "../Database/DatabaseProperty";
import OneUptimeDate from "../Date";
import BadDataException from "../Exception/BadDataException";
import { ObjectType } from "../JSON";
import JSONFunctions from "../JSONFunctions";
import PositiveNumber from "../PositiveNumber";
import EventInterval from "./EventInterval";
export default class Recurring extends DatabaseProperty {
    static getDefaultRotationData() {
        return {
            intervalType: EventInterval.Day,
            intervalCount: new PositiveNumber(1),
        };
    }
    static getNextDateInterval(startDate, rotation, getDateInThePast) {
        const intervalType = rotation.intervalType;
        const intervalCount = rotation.intervalCount;
        // past or present date.
        const multiplier = getDateInThePast ? -1 : 1;
        let nextDate = OneUptimeDate.fromString(startDate);
        switch (intervalType) {
            case EventInterval.Hour:
                nextDate = OneUptimeDate.addRemoveHours(nextDate, intervalCount.toNumber() * multiplier);
                break;
            case EventInterval.Day:
                nextDate = OneUptimeDate.addRemoveDays(nextDate, intervalCount.toNumber() * multiplier);
                break;
            case EventInterval.Week:
                nextDate = OneUptimeDate.addRemoveDays(nextDate, intervalCount.toNumber() * 7 * multiplier);
                break;
            case EventInterval.Month:
                nextDate = OneUptimeDate.addRemoveMonths(nextDate, intervalCount.toNumber() * multiplier);
                break;
            case EventInterval.Year:
                nextDate = OneUptimeDate.addRemoveYears(nextDate, intervalCount.toNumber() * multiplier);
                break;
            default:
                throw new BadDataException("Invalid Interval Type: " + intervalType);
        }
        return nextDate;
    }
    static getNextDate(startDate, rotation) {
        let nextDate = OneUptimeDate.fromString(startDate);
        const dateNow = OneUptimeDate.getCurrentDate();
        if (nextDate.getTime() <= dateNow.getTime()) {
            const intervalType = rotation.intervalType;
            const intervalCount = rotation.intervalCount;
            const diff = dateNow.getTime() - nextDate.getTime();
            let intervalMillis;
            switch (intervalType) {
                case EventInterval.Hour:
                    intervalMillis = intervalCount.toNumber() * 3600000;
                    break;
                case EventInterval.Day:
                    intervalMillis = intervalCount.toNumber() * 86400000;
                    break;
                case EventInterval.Week:
                    intervalMillis = intervalCount.toNumber() * 604800000;
                    break;
                case EventInterval.Month:
                    intervalMillis = intervalCount.toNumber() * 2629800000; // Approximate month in milliseconds
                    break;
                case EventInterval.Year:
                    intervalMillis = intervalCount.toNumber() * 31557600000; // Approximate year in milliseconds
                    break;
                default:
                    throw new BadDataException("Invalid Interval Type: " + intervalType);
            }
            const intervalsToAdd = Math.ceil(diff / intervalMillis);
            nextDate = new Date(nextDate.getTime() + intervalsToAdd * intervalMillis);
        }
        return nextDate;
    }
    get intervalType() {
        return this.data.intervalType;
    }
    set intervalType(v) {
        this.data.intervalType = v;
    }
    // intervalCount
    get intervalCount() {
        return this.data.intervalCount;
    }
    set intervalCount(v) {
        this.data.intervalCount = v;
    }
    constructor() {
        super();
        this.data = Recurring.getDefaultRotationData();
        this.data = Recurring.getDefaultRotationData();
    }
    static getDefault() {
        return new Recurring();
    }
    toJSON() {
        return JSONFunctions.serialize({
            _type: ObjectType.Recurring,
            value: {
                intervalType: this.intervalType,
                intervalCount: this.intervalCount.toJSON(),
            },
        });
    }
    static fromJSONArray(json) {
        const arrayToReturn = [];
        for (const item of json) {
            arrayToReturn.push(this.fromJSON(item));
        }
        return arrayToReturn;
    }
    static fromJSON(json) {
        if (json instanceof Recurring) {
            return json;
        }
        if (!json || json["_type"] !== ObjectType.Recurring) {
            throw new BadDataException("Invalid Rotation");
        }
        if (!json["value"]) {
            throw new BadDataException("Invalid Rotation");
        }
        json = json["value"];
        let intervalType = EventInterval.Day;
        if (json && json["intervalType"]) {
            intervalType = json["intervalType"];
        }
        let intervalCount = new PositiveNumber(1);
        if (json && json["intervalCount"]) {
            intervalCount = PositiveNumber.fromJSON(json["intervalCount"]);
        }
        const rotation = new Recurring();
        rotation.data = {
            intervalType,
            intervalCount,
        };
        return rotation;
    }
    static toJSONArray(recurrings) {
        const arrayToReturn = [];
        for (const item of recurrings) {
            arrayToReturn.push(item.toJSON());
        }
        return arrayToReturn;
    }
    toString() {
        return `${this.intervalCount} ${this.intervalType}`;
    }
    static toDatabase(value) {
        if (Array.isArray(value)) {
            return this.toJSONArray(value);
        }
        if (value && value instanceof Recurring) {
            return value.toJSON();
        }
        else if (value) {
            return JSONFunctions.serialize(value);
        }
        return null;
    }
    static fromDatabase(value) {
        if (Array.isArray(value)) {
            return Recurring.fromJSONArray(value);
        }
        if (value) {
            return Recurring.fromJSON(value);
        }
        return null;
    }
}
//# sourceMappingURL=Recurring.js.map