// Copyright (C) 2026 Kiyotsugu Arai
// SPDX-License-Identifier: LGPL-3.0-or-later

// IntIO.hpp
// 多倍長整数の入出力に関する操作を定義

#ifndef CALX_INT_IO_HPP
#define CALX_INT_IO_HPP

#include <math/core/mp/Int/IntBase.hpp>
#include <string>
#include <span>
#include <vector>
#include <cstring>

namespace calx {

    /**
     * @brief 整数の書式設定オプション
     */
    struct FormatOptions {
        int base = 10;         ///< 基数（2～36）
        bool showSign = false; ///< 正の値の場合も符号を表示
        bool showBase = false; ///< 基数プレフィックスを表示（0x, 0b, 0など）
        bool uppercase = false; ///< 16進数などで大文字を使用
        int width = 0;         ///< 最小幅（0は制限なし）
        bool zeroPad = false;  ///< 0埋め（widthが指定されている場合）
    };

    /**
     * @brief 多倍長整数の入出力ユーティリティクラス
     *
     * このクラスは、Intクラスの文字列変換など、入出力に関する
     * ユーティリティメソッドを提供します。
     */
    class IntIOUtils {
    public:
        /**
         * @brief ワード配列から16進数文字列に変換
         * @param words ワード配列
         * @param sign 符号
         * @return 16進数文字列
         */
        static std::string fromRawWords(const std::vector<uint64_t>& words, int sign);

        /**
         * @brief 整数を文字列に変換
         * @param value 変換する整数
         * @param base 基数（2～36）
         * @return 文字列表現
         */
        static std::string toString(const Int& value, int base = 10);

        /**
         * @brief 文字列から整数に変換
         * @param str 変換する文字列
         * @param base 基数（0=自動判定, 2～36）
         * @return 整数値
         */
        static Int fromString(std::string_view str, int base = 0);

        /**
         * @brief 整数を指定された書式で文字列に変換
         * @param value 変換する整数
         * @param options 書式設定オプション
         * @return 整形された文字列
         */
        static std::string format(const Int& value, const FormatOptions& options);

        /// fromString の Horner/DC 切り替え閾値を設定 (チューニング用)
        static void setFromStringDCThreshold(size_t threshold);
        static size_t getFromStringDCThreshold();

        /// エンディアン指定
        enum class Endian { Little, Big, Native };

        /**
         * @brief 整数をポータブルバイナリ形式にエクスポート
         *
         * フォーマット: [sign:1byte][size:4bytes LE][words:size*8bytes]
         *   sign: 0=zero, 1=positive, 0xFF=negative
         *   size: ワード数 (LE 4バイト)
         *   words: 各 64bit ワード (指定エンディアン, LSW first)
         *
         * @param value エクスポートする整数
         * @param endian ワードのバイトオーダー (デフォルト Little)
         * @return バイナリデータ
         */
        static std::vector<uint8_t> exportBinary(const Int& value,
                                                  Endian endian = Endian::Little);

        /**
         * @brief ポータブルバイナリ形式から整数をインポート
         *
         * exportBinary で生成されたデータからIntを復元する。
         *
         * @param data バイナリデータ
         * @param endian ワードのバイトオーダー (エクスポート時と同じ)
         * @return 復元された整数
         * @throws std::invalid_argument データが不正な場合
         */
        static Int importBinary(std::span<const uint8_t> data,
                                Endian endian = Endian::Little);
    };

} // namespace calx

#endif // CALX_INT_IO_HPP