#include "Axis_Format.h"

#include <algorithm>
#include <iomanip>
#include <sstream>

namespace renderive::detail {
namespace {

std::string fixed_number(double value, int precision) {
    std::ostringstream stream;
    stream << std::fixed << std::setprecision(std::clamp(precision, 0, 12)) << value;
    std::string result = stream.str();
    if (result.find('.') != std::string::npos) {
        while (!result.empty() && result.back() == '0')
            result.pop_back();
        if (!result.empty() && result.back() == '.')
            result.pop_back();
    }
    return result;
}

std::string digits(int value, int width) {
    std::ostringstream stream;
    stream << std::setfill('0') << std::setw(width) << value;
    return stream.str();
}

} // namespace

std::string localized_axis_number(double value, int precision, Number_Locale locale) {
    std::string result = fixed_number(value, precision);
    if (locale.decimal_point != '.')
        std::replace(result.begin(), result.end(), '.', locale.decimal_point);
    return result;
}

std::string formatted_axis_time(Time_Of_Day time, std::string_view format) {
    const auto total = time.milliseconds;
    const int hours = static_cast<int>((total / 3'600'000) % 24);
    const int minutes = static_cast<int>((total / 60'000) % 60);
    const int seconds = static_cast<int>((total / 1'000) % 60);
    const int milliseconds = static_cast<int>(total % 1'000);
    std::string result;
    for (std::size_t index = 0; index < format.size();) {
        const std::string_view rest = format.substr(index);
        if (rest.starts_with("zzz")) {
            result += digits(milliseconds, 3);
            index += 3;
        } else if (rest.starts_with("hh") || rest.starts_with("HH")) {
            result += digits(hours, 2);
            index += 2;
        } else if (rest.starts_with("mm")) {
            result += digits(minutes, 2);
            index += 2;
        } else if (rest.starts_with("ss")) {
            result += digits(seconds, 2);
            index += 2;
        } else {
            result.push_back(format[index++]);
        }
    }
    return result;
}

} // namespace renderive::detail
