-- | Simple graphviz output.
module Data.Graph.Inductive.Graphviz(
    Orient(..),
    graphviz, graphviz'
) where

import Data.Graph.Inductive.Graph

data Orient = Portrait | Landscape deriving (Eq, Show)

o2s :: Orient -> String
o2s Portrait = "\trotate = \"0\"\n"
o2s Landscape = "\trotate = \"90\"\n"

-- | Formats a graph for use in graphviz.
graphviz :: (Graph g, Show a, Show b) =>    g a b   -- ^ The graph to format
					 -> String  -- ^ The title of the graph
					 -> (Double, Double)	-- ^ The size
								-- of the page
					 -> (Int, Int)	-- ^ The width and
							-- height of the page
							-- grid
					 -> Orient  -- ^ The orientation of
						    -- the graph.
					 -> String

i2d :: Int -> Double
i2d = fromInteger . toInteger

graphviz g t (w, h) p@(pw', ph') o =
    let n = labNodes g
	e = labEdges g
	ns = concatMap sn n
	es = concatMap se e
	sz w' h' = if o == Portrait then show w'++","++show h' else show h'++","++show w'
	ps = show w++","++show h
	(pw, ph) = if o == Portrait then p else (ph', pw')
	--gs = show ((w*(i2d pw))-m)++","++show ((h*(i2d ph))-m)
	gs = sz (w*(i2d pw)) (h*(i2d ph))
    in "digraph "++t++" {\n"
	    ++"\tmargin = \"0\"\n"
	    ++"\tpage = \""++ps++"\"\n"
	    ++"\tsize = \""++gs++"\"\n"
	    ++o2s o
	    ++"\tratio = \"fill\"\n"
	    ++ns
	    ++es
	++"}"
    where sn (n, a) | sa == ""	= ""
		    | otherwise	= '\t':(show n ++ sa ++ "\n")
	    where sa = sl a
	  se (n1, n2, b) = '\t':(show n1 ++ " -> " ++ show n2 ++ sl b ++ "\n")

-- | Format a graph for graphviz with reasonable defaults: title of \"fgl\",
-- 8.5x11 pages, one page, landscape orientation
graphviz' :: (Graph g, Show a, Show b) => g a b -> String
graphviz' g = graphviz g "fgl" (8.5,11.0) (1,1) Landscape

sq :: String -> String
sq ('"':s) | last s == '"'  = init s
	   | otherwise	    = s
sq ('\'':s) | last s == '\''	= init s
	    | otherwise		= s
sq s = s

sl :: (Show a) => a -> String
sl a =
    let l = sq (show a)
    in if (l /= "()") then (" [label = \""++l++"\"]") else ""
