;;; dag-draw-dot.el --- DOT format rendering for dag-draw -*- lexical-binding: t -*-

;; Copyright (C) 2024, 2025

;; Author: Generated by Claude
;; Keywords: internal

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;;; Commentary:

;; DOT format (Graphviz) rendering implementation for dag-draw graphs.
;; Exports positioned graphs to Graphviz DOT format for external processing.

;;; Code:

(require 'dag-draw-core)

;;; DOT Format Rendering

(defun dag-draw-render-dot (graph &optional selected)
  "Render GRAPH in Graphviz DOT format.

GRAPH is a `dag-draw-graph' structure containing nodes and edges.

SELECTED is an optional node ID (symbol) to render with selection highlighting.
Selected nodes are rendered with style=bold attribute for visual emphasis.

Creates a DOT language representation suitable for processing with
Graphviz tools.  Includes node declarations with labels and edge
declarations with optional edge labels.

Returns a string containing the complete DOT format graph specification."
  (let ((dot-output "digraph G {\n")
        (node-attrs "  node [shape=box, style=filled, fillcolor=lightgray];\n")
        (edge-attrs "  edge [color=black];\n")
        ;; Only use selection if the node actually exists in the graph
        (valid-selected (and selected (dag-draw-get-node graph selected) selected)))

    ;; Add graph attributes
    (setq dot-output (concat dot-output node-attrs edge-attrs "\n"))

    ;; Add nodes
    (ht-each (lambda (node-id node)
               (let ((label (dag-draw-node-label node))
                     (is-selected (and valid-selected (eq node-id valid-selected))))
                 (setq dot-output
                       (concat dot-output
                               (format "  %s [label=\"%s\"%s];\n"
                                       (symbol-name node-id)
                                       (dag-draw--escape-dot-string label)
                                       (if is-selected ", style=bold" ""))))))
             (dag-draw-graph-nodes graph))

    ;; Add edges
    (setq dot-output (concat dot-output "\n"))
    (dolist (edge (dag-draw-graph-edges graph))
      (let ((from (symbol-name (dag-draw-edge-from-node edge)))
            (to (symbol-name (dag-draw-edge-to-node edge)))
            (label (dag-draw-edge-label edge)))
        (setq dot-output
              (concat dot-output
                      (format "  %s -> %s" from to)
                      (if label
                          (format " [label=\"%s\"]" (dag-draw--escape-dot-string label))
                        "")
                      ";\n"))))

    (concat dot-output "}\n")))

(defun dag-draw--escape-dot-string (text)
  "Escape special characters in TEXT for DOT format.

TEXT is a string that may contain DOT special characters.

Escapes backslashes and double quotes to ensure valid DOT syntax.
Backslashes are escaped first to avoid double-escaping.

Returns the escaped string safe for use in DOT labels and attributes."
  ;; Escape backslashes first (each \ becomes \\\\), then quotes (each " becomes \\")
  (replace-regexp-in-string
   "\"" "\\\\\\\\\""
   (replace-regexp-in-string "\\\\" "\\\\\\\\\\\\\\\\" text)))

(provide 'dag-draw-dot)

;;; dag-draw-dot.el ends here