import System.Process(system)
import qualified Data.Map as M
import qualified Data.Set as S
import Data.List


-- building a table of RGL functions and their types, examples, and documentation
-- to run:
--   $ runghc AbsFunDoc.hs >absfuns.txt
--   $ txt2tags -thtml absfuns.txt
-- this creates the file absfuns.html

main = do
  system "grep \" : \" ../src/abstract/*.gf | grep \" -- \" >absfuns.tmp"
  funs <- readFile "absfuns.tmp" >>= return . lines
  deps <- readFile "../src/Lang.labels" >>= return . lines
  let depmap = M.fromListWith (\x y -> x ++ [";"] ++ y) [(fun,deps) | fun:deps <- map words deps]
  let rows = sort $ filter (flip S.notMember hiddenModules . last) $ map (mkRow depmap) (map words funs)
  let entries = map (sepFields . addLink) rows
  putStrLnIf $ "GF RGL Functions"
  putStrLnIf $ "generated by lib/src/doc/AbsFunFoc.hs"
  putStrLnIf $ "%%date"
  putStrLnIf $ ""
  putStrLnIf $ "Functions in this table have links, e.g. http://www.grammaticalframework.org/lib/doc/absfuns.html#PredVP"
  putStrLn $ sepFields ["**Function**","**Type**","**Example**","**Dependencies**","**Module**"]
  putStrLn $ unlines entries


hiddenModules = S.fromList
  ["Backward","Structural","Extra","Compatibility",
   "Documentation","Lexicon","NumeralTransfer","Terminology","Transfer","MarkHTML","Markup","ERROR"] ----

mkRow depmap ws = case ws of
  file:fun:":":typecomment -> named fun : getTypeComment typecomment ++ [getDep fun, getModule file]
  _ -> ["ERROR"]
 where
   getModule = reverse . takeWhile (/='/') . tail . dropWhile (/='.') . reverse -- ../src/abstract/Adverb.gf: --> Adverb
   getTypeComment ws = case span (/= ";") ws of
     (ty,rest) -> [unwords ty, italics (unwords (drop 2 rest))]  -- PredVP    : NP -> VP -> Cl ; -- John walks
   getDep fun = maybe "-" (unwords . takeWhile (/="--")) $ M.lookup fun depmap

-- for html (via txt2tags) generation
sepFields fs = "| " ++ concat (intersperse " | " fs) ++ " |"
named f = f ++ "''<a name=\"" ++ f ++ "\"></a>''"
italics e = "//" ++ map (\c -> case c of '[' -> '(' ; ']'->')'; _ -> c) e ++ "//"
putStrLnIf = putStrLn
addLink fs =
  let
    m = last fs
    abstract = "abstract/"
  in init fs ++ ["[" ++ m ++ " ../src/" ++ abstract ++ m ++ ".gf]"]

-- for tab separated generation
-- sepFields = concat . intersperse "\t"
-- named f = f
-- italics e = e
-- putStrLnIf = return ()
-- addLink fs = fs
