{-# LANGUAGE MonoLocalBinds #-}
module Byg.DependencyFormatter
  ( formatDependencyTrees
  ) where

import Byg.Types.Token (Token(..))
import Byg.Types.Dependency (Dependency(..), Action(..))

import Type.Reflection (TypeRep, typeRep)
import Text.Printf (printf)
import Data.Text (Text)
import qualified Data.Text as T

formatDependencyTrees :: [Dependency] -> Text
formatDependencyTrees = T.concat . (formatDependencyTrees' "")
  where formatDependencyTrees' indentation = concatMap (formatDependencyTree indentation)

        formatDependencyTree indentation (Dependency _ a action _ b) =
          concat [ [ indentation ]
                 , formatToken a
                 , [ " -> " ]
                 , formatToken b
                 , [ ": " ]
                 , formatAction indentation action
                 ]

        formatToken :: Token a -> [Text]
        formatToken = \case
          Token i ->
            [ T.pack (printf "%03d" i) ]
          TupleToken a b ->
            concat [ [ "tup(" ]
                   , formatToken a
                   , [ ", " ]
                   , formatToken b
                   , [ ")" ]
                   ]
          ZipToken a b ->
            concat [ [ "zip(" ]
                   , formatToken a
                   , [ ", " ]
                   , formatToken b
                   , [ ")" ]
                   ]
          ListToken ts ->
            [ "["
            , T.intercalate ", " (map (T.concat . formatToken) ts)
            , "]"
            ]
          NoToken ->
            [ "--" ]

        formatAction :: forall a b. Text -> Action a b -> [Text]
        formatAction indentation = \case
          Function _ ->
            [ "Function "
            , T.pack (show (typeRep :: TypeRep a))
            , " -> "
            , T.pack (show (typeRep :: TypeRep b))
            , "\n"
            ]
          MapComp subDeps innerInput innerOutput ->
            concat [ [ "MapComp(" ]
                   , formatToken innerInput
                   , [ " -> " ]
                   , formatToken innerOutput
                   , [ "):\n" ]
                   , formatDependencyTrees' (T.append indentation "|  ") subDeps
                   ]
          action ->
            [ T.pack (show action)
            , "\n"
            ]
