/*
 * Copyright 2015 - 2025 gary@drinkingtea.net
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

#pragma once

#include "bit.hpp"
#include "error.hpp"
#include "math.hpp"
#include "types.hpp"
#include "writer.hpp"

namespace ox {

template<Integer_c Integer>
constexpr ox::Error writeItoa(Integer const v, ox::Writer_c auto &writer) noexcept {
	if (v) {
		ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
		ox::ResizedInt_t<Integer, 64> val = v;
		constexpr auto base = 10;
		auto it = 0;
		if (val < 0) {
			OX_RETURN_ERROR(writer.put('-'));
			val = ~val + 1;
		}
		if constexpr(sizeof(v) == 8 && !ox::is_signed_v<Integer>) {
			auto digit = val / mod;
			val %= mod;
			mod /= base;
			if (digit) {
				digit -= 10;
				OX_RETURN_ERROR(writer.put('1'));
				OX_RETURN_ERROR(writer.put(static_cast<char>('0' + digit)));
				++it;
			}
		}
		while (mod) {
			auto const digit = val / mod;
			val %= mod;
			mod /= base;
			if (it || digit) {
				OX_RETURN_ERROR(writer.put(static_cast<char>('0' + digit)));
				++it;
			}
		}
	} else {
		// 0 is a special case
		OX_RETURN_ERROR(writer.put('0'));
	}
	return {};
}

}

#include "istring.hpp"
