/*
 * Mirai. Copyright (C) 2024 Vyn
 * This file is licensed under version 3 of the GNU General Public License (GPL-3.0-only)
 * The license can be found in the LICENSE file or at https://www.gnu.org/licenses/gpl-3.0.txt
 */

#include "Utils.h"
#include <cctype>
#include <chrono>
#include <format>
#include <string>

void bindSlintUtils(const ui::Utils &utils)
{
	utils.on_format_date([&](const ui::Date &date) {
		std::chrono::year_month_day chronoDate{
			std::chrono::year(date.year),
			std::chrono::month(date.month),
			std::chrono::day(date.day),
		};
		return std::format("{:%B %d}", chronoDate);
	});

	auto currentDate = MiraiDateToSlintDate(mirai::Date(std::chrono::system_clock::now()));
	utils.set_current_date(currentDate);

	auto currentTime = MiraiTimeToSlintTime(mirai::Time(std::chrono::system_clock::now()));
	utils.set_current_time(currentTime);
}

std::string formatZeroPadding(const int number)
{
	if (number < 10) {
		return "0" + std::to_string(number);
	}
	return std::to_string(number);
}

std::string formatDateRelative(const ui::Date &date)
{
	auto todayDate = mirai::Date(std::chrono::system_clock::now());
	auto relativeDaysDiff = std::chrono::duration_cast<std::chrono::days>(
								std::chrono::sys_days(SlintDateToMiraiDate(date).toStdChrono()) -
								std::chrono::sys_days(todayDate.toStdChrono())
	)
								.count();

	if (relativeDaysDiff == 0) {
		return std::string("today");
	} else if (relativeDaysDiff == 1) {
		return std::string("tomorrow");
	}
	return std::format("in {} days", relativeDaysDiff);
};

std::string capitalize(std::string str)
{
	str[0] = static_cast<char>(toupper(str[0]));
	return str;
};

std::string SlintDateToStdString(const ui::Date &date)
{
	return std::to_string(date.year) + "-" + formatZeroPadding(date.month) + "-" +
		   formatZeroPadding(date.day);
}

mirai::Date SlintDateToMiraiDate(const ui::Date &date)
{
	return mirai::Date(
		date.year, static_cast<unsigned>(date.month), static_cast<unsigned>(date.day)
	);
}

ui::Date MiraiDateToSlintDate(const mirai::Date &date)
{
	return {
		.year = date.year,
		.month = static_cast<int>(date.month),
		.day = static_cast<int>(date.day),
	};
}

ui::Time MiraiTimeToSlintTime(const mirai::Time &time)
{
	return {.hour = time.hour, .minute = time.minute, .second = 0};
}

mirai::Time SlintTimeToMiraiTime(const ui::Time &time)
{
	return mirai::Time{time.hour, time.minute};
}
