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

/**
 * @file svg_writer.hpp
 * @brief SVG 出力 (DRW-50)
 *
 * 描画操作を SVG ファイルとして出力。ベクタ形式で無劣化。
 */

#ifndef CALX_IMAGE_IO_SVG_WRITER_HPP
#define CALX_IMAGE_IO_SVG_WRITER_HPP

#include <string>
#include <sstream>
#include <fstream>
#include <cmath>
#include <iomanip>

namespace calx::image {

class SVGWriter {
public:
    SVGWriter(int width, int height) : w_(width), h_(height) {
        ss_ << R"(<?xml version="1.0" encoding="UTF-8"?>)" << "\n";
        ss_ << "<svg xmlns=\"http://www.w3.org/2000/svg\" "
            << "width=\"" << w_ << "\" height=\"" << h_ << "\" "
            << "viewBox=\"0 0 " << w_ << " " << h_ << "\">\n";
    }

    /// 背景色
    SVGWriter& background(const std::string& color = "white") {
        ss_ << "  <rect width=\"100%\" height=\"100%\" fill=\"" << color << "\"/>\n";
        return *this;
    }

    /// 線分
    SVGWriter& line(double x1, double y1, double x2, double y2,
                     const std::string& stroke = "black", double strokeWidth = 1,
                     const std::string& dashArray = "") {
        ss_ << "  <line x1=\"" << x1 << "\" y1=\"" << y1
            << "\" x2=\"" << x2 << "\" y2=\"" << y2
            << "\" stroke=\"" << stroke << "\" stroke-width=\"" << strokeWidth << "\"";
        if (!dashArray.empty()) ss_ << " stroke-dasharray=\"" << dashArray << "\"";
        ss_ << "/>\n";
        return *this;
    }

    /// 矩形
    SVGWriter& rect(double x, double y, double w, double h,
                     const std::string& fill = "none",
                     const std::string& stroke = "black", double strokeWidth = 1,
                     double rx = 0) {
        ss_ << "  <rect x=\"" << x << "\" y=\"" << y
            << "\" width=\"" << w << "\" height=\"" << h << "\"";
        if (rx > 0) ss_ << " rx=\"" << rx << "\"";
        ss_ << " fill=\"" << fill << "\" stroke=\"" << stroke
            << "\" stroke-width=\"" << strokeWidth << "\"/>\n";
        return *this;
    }

    /// 円
    SVGWriter& circle(double cx, double cy, double r,
                       const std::string& fill = "none",
                       const std::string& stroke = "black", double strokeWidth = 1) {
        ss_ << "  <circle cx=\"" << cx << "\" cy=\"" << cy << "\" r=\"" << r
            << "\" fill=\"" << fill << "\" stroke=\"" << stroke
            << "\" stroke-width=\"" << strokeWidth << "\"/>\n";
        return *this;
    }

    /// 楕円
    SVGWriter& ellipse(double cx, double cy, double rx, double ry,
                        const std::string& fill = "none",
                        const std::string& stroke = "black", double strokeWidth = 1) {
        ss_ << "  <ellipse cx=\"" << cx << "\" cy=\"" << cy
            << "\" rx=\"" << rx << "\" ry=\"" << ry
            << "\" fill=\"" << fill << "\" stroke=\"" << stroke
            << "\" stroke-width=\"" << strokeWidth << "\"/>\n";
        return *this;
    }

    /// テキスト
    SVGWriter& text(double x, double y, const std::string& content,
                     double fontSize = 16,
                     const std::string& fill = "black",
                     const std::string& fontFamily = "sans-serif") {
        ss_ << "  <text x=\"" << x << "\" y=\"" << y
            << "\" font-size=\"" << fontSize
            << "\" font-family=\"" << fontFamily
            << "\" fill=\"" << fill << "\">"
            << content << "</text>\n";
        return *this;
    }

    /// パス (SVG path d 属性)
    SVGWriter& path(const std::string& d,
                     const std::string& fill = "none",
                     const std::string& stroke = "black", double strokeWidth = 1) {
        ss_ << "  <path d=\"" << d << "\" fill=\"" << fill
            << "\" stroke=\"" << stroke << "\" stroke-width=\"" << strokeWidth
            << "\"/>\n";
        return *this;
    }

    /// ポリライン
    SVGWriter& polyline(const std::vector<std::pair<double,double>>& pts,
                         const std::string& stroke = "black", double strokeWidth = 1,
                         const std::string& fill = "none") {
        ss_ << "  <polyline points=\"";
        for (auto& [x,y] : pts) ss_ << x << "," << y << " ";
        ss_ << "\" fill=\"" << fill << "\" stroke=\"" << stroke
            << "\" stroke-width=\"" << strokeWidth << "\"/>\n";
        return *this;
    }

    /// 生の SVG 要素を追加
    SVGWriter& raw(const std::string& svgElement) {
        ss_ << "  " << svgElement << "\n";
        return *this;
    }

    /// SVG 文字列を取得
    std::string toString() const {
        return ss_.str() + "</svg>\n";
    }

    /// ファイルに保存
    void save(const std::string& path) const {
        std::ofstream ofs(path);
        if (!ofs) return;
        ofs << toString();
    }

private:
    int w_, h_;
    std::stringstream ss_;
};

} // namespace calx::image

#endif
