(ns wanijo.visualisation.viz
  (:require [clojure.string :refer [replace] :rename {replace sreplace}]
            [dorothy
             [core :as dot]
             [jvm :as doro-jvm]]
            [wanijo.infrastructure.routing :refer [path]]))

(defn node->label
  ([node]
   (:name node))
  ([node1 node2]
   (str (:name node1)
        "\n"
        (:name node2))))

(defn render [data]
  (-> data
      dot/digraph
      dot/dot
      (doro-jvm/render {:format :svg})
      (sreplace #"width=\"[0-9]+pt\"" "")))

(defn single-instance [instance]
  (let [out-nodes (map #(vector (-> % :target :uuid)
                                {:label (node->label (:target %))
                                 :href (path :instance-show (:target %))})
                       (:links-out instance))
        in-nodes (map #(vector (-> % :source :uuid)
                               {:label (node->label (:source %))
                                :href (path :instance-show (:source %))})
                      (:links-in instance))
        relationships-out (map (fn [{:keys [link target schema]}]
                                 [(:uuid instance) :> (:uuid target)
                                  {:label (:name link)}])
                               (:links-out instance))
        relationships-in (map (fn [{:keys [link source schema]}]
                                [(:uuid source) :> (:uuid instance)
                                 {:label (:name link)}])
                              (:links-in instance))
        rankdir (if (or (> (count in-nodes) 5)
                        (> (count out-nodes) 5))
                  "LR"
                  "TD")]
    (-> [{:rankdir rankdir}
         [(:uuid instance) {:label (node->label instance)
                            :shape "cylinder"}]]
        (into out-nodes)
        (into in-nodes)
        (into relationships-out)
        (into relationships-in)
        render)))

(defn all-instances [instances]
  (let [sources (map #(vector (-> % :source :uuid)
                              {:label (node->label (:source %)
                                                   (:schema %))
                               :href (path :instance-show (:source %))})
                     instances)
        linked (filter :link instances)
        links (map #(vector (-> % :source :uuid)
                            :>
                            (-> % :target :uuid)
                            {:label (-> % :link :name)})
                   linked)]
    (-> [{:forcelabels "true"
          :rankdir "LR"}]
        (into sources)
        (into links)
        render)))
