"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TimeCalc = void 0;
const suncalc_1 = __importDefault(require("suncalc"));
const date_fns_1 = require("date-fns");
class TimeCalc {
    constructor(latitude, longitude, wrapMidnight, startTime, endTime, startOffset, endOffset) {
        this.latitude = latitude;
        this.longitude = longitude;
        this.wrapMidnight = wrapMidnight;
        this.startTime = startTime;
        this.endTime = endTime;
        this.startOffset = startOffset;
        this.endOffset = endOffset;
        this.sunTimes = undefined;
        this.moonTimes = undefined;
        this.sunLookup = {
            5000: 'dawn',
            5001: 'dusk',
            5002: 'solarNoon',
            5003: 'sunrise',
            5004: 'sunset',
            5005: 'night',
            5006: 'nightEnd',
            5007: 'rise',
            5008: 'set',
        };
        this.lastSuncalcUpdate = -1;
        this.actualStart = 0;
        this.actualEnd = 0;
        this.eventCalculation();
    }
    debug() {
        const sunTimes = Object.fromEntries(Object.values(this.sunLookup)
            .filter((key) => (this.sunTimes && key in this.sunTimes))
            .map((key) => {
            if (this.sunTimes && (key in this.sunTimes)) {
                return [key, this.getMinutes(this.sunTimes[key])];
            }
            return [key, -1];
        }));
        const moonTimes = Object.fromEntries(Object.values(this.sunLookup)
            .filter((key) => (this.moonTimes && key in this.moonTimes))
            .map((key) => {
            if (this.moonTimes && (key in this.moonTimes)) {
                return [key, this.getMinutes(this.moonTimes[key])];
            }
            return [key, -1];
        }));
        return {
            sunTimes,
            moonTimes,
            now: this.getMinutes(new Date()),
            actualStart: this.actualStart,
            actualEnd: this.actualEnd,
            nextStart: this.getMinutesToNextStartEvent(),
            nextEnd: this.getMinutesToNextEndEvent(),
            onState: this.getOnState(),
            noOnStateToday: this.noOnStateToday()
        };
    }
    setStartEndTime(startTime, endTime, startOffset, endOffset) {
        this.startTime = startTime ?? this.startTime;
        this.endTime = endTime ?? this.endTime;
        this.startOffset = startOffset ?? this.startOffset;
        this.endOffset = endOffset ?? this.endOffset;
        this.eventCalculation();
    }
    getMinutesToNextStartEvent(date = new Date()) {
        const currentTime = this.getMinutes(date);
        const nextEvent = this.actualStart - currentTime;
        return nextEvent >= 0 ? nextEvent : nextEvent + 1440;
    }
    getMinutesToNextEndEvent(date = new Date()) {
        const currentTime = this.getMinutes(date);
        const nextEvent = this.actualEnd - currentTime;
        return nextEvent >= 0 ? nextEvent : nextEvent + 1440;
    }
    getOnState(date = new Date()) {
        const currentTime = (0, date_fns_1.hoursToMinutes)(date.getHours()) + date.getMinutes();
        if (this.actualEnd < this.actualStart) {
            return this.wrapMidnight && ((currentTime < this.actualEnd) || (currentTime > this.actualStart));
        }
        return (currentTime > this.actualStart) && (currentTime < this.actualEnd);
    }
    noOnStateToday() {
        return !this.wrapMidnight && (this.actualEnd < this.actualStart);
    }
    eventCalculation(now = new Date()) {
        this.updateSunCalc(now);
        this.actualStart = this.lookupEventTime(this.startTime) + this.startOffset;
        this.actualEnd = this.lookupEventTime(this.endTime, this.actualStart) + this.endOffset;
    }
    getMinutes(date) {
        return date.getHours() * 60 + date.getMinutes();
    }
    updateSunCalc(now = new Date()) {
        if (this.lastSuncalcUpdate === now.getDay()) {
            return;
        }
        this.lastSuncalcUpdate = now.getDay();
        this.sunTimes = suncalc_1.default.getTimes(now, this.latitude, this.longitude);
        this.moonTimes = suncalc_1.default.getMoonTimes(now, this.latitude, this.longitude);
    }
    lookupEventTime(time, startTime = 0) {
        if (time <= 1440) {
            return time;
        }
        if (time > 10000) {
            return (startTime + (time - 10000)) % 1440;
        }
        const v = this.sunLookup[time];
        if (this.sunTimes && v in this.sunTimes) {
            const z = this.sunTimes[v];
            return (this.getMinutes(z));
        }
        if (this.moonTimes && v in this.moonTimes) {
            const z = this.moonTimes[v];
            return typeof z === 'object'
                ? this.getMinutes(z)
                : (v === 'set' ? 1440 : 0);
        }
        throw new Error('Time is more than 1440 (60*24)');
    }
}
exports.TimeCalc = TimeCalc;
