/*
 * @author  xamidev <xamidev@riseup.net>
 * @brief   Date helper functions
 * @license GPL-3.0-only
 */

#include <stdint.h>
#include <time/date.h>
#include <mem/utils.h>
#include <kernel.h>

extern struct boot_context boot_ctx;

// Unix epoch used as reference: Jan 1st 1970, 00:00:00 UTC
struct date epoch = {
    .year = 1970,
    .month = 1,
    .day = 1,
    .hour = 0,
    .minute = 0,
    .second = 0
};

/*
 * date_timestamp_to_date - Convert UNIX timestamp to a date structure
 * @timestamp: UNIX timestamp
 * 
 * Return:
 * <date> - date structure
 */
struct date date_timestamp_to_date(uint64_t timestamp)
{
    struct date result;
    memcpy(&result, &epoch, sizeof(struct date));
    uint64_t nr_days = timestamp / 86400;

    while (nr_days > 0) {
        unsigned int nr_month = 0;
        int leap_year = 0;

        if (result.year % 4 == 0 && (result.year % 100 != 0 || result.year % 400 == 0)) {
            leap_year = 1;
        } else {
            leap_year = 0;
        }

        if (result.month == 2) {
            if (leap_year != 0) {
                nr_month = 29;
            } else {
                nr_month = 28;
            }
        } else {
            nr_month = 31 - ((result.month -1) % 7 % 2);
        }
        
        if (nr_days >= nr_month) {
            nr_days -= nr_month;
            result.month++;
            if (result.month > 12) {
                result.month = 1;
                result.year++;
            }
        } else {
            result.day += nr_days;
            nr_days = 0;
        }
    }

    result.second = timestamp % 60;
    timestamp /= 60;
    result.minute = timestamp % 60;
    timestamp /= 60;
    result.hour = timestamp % 24;

    return result;
}

/*
 * date_now - Get the current date (time at boot + timer ticks)
 *
 * Return:
 * <date> - date structure
 */
struct date date_now()
{
    uint64_t timestamp_now = boot_ctx.bootdate->boot_time + (ticks/1000);
    return date_timestamp_to_date(timestamp_now);
}