module Test.SBench.File.Types ( MetaInfo(..), Range(..) ) where

import Test.SBench.Options ( EvalMod )

-- | Metainformation stored in the header of all .sbench files.
--   Part of the 'MetaInfo' entries are usually calculated automatically.
data (Real a, Real b) => MetaInfo a b = MetaInfo
  { header           :: [String]
  , sbenchVersion    :: String
  , miGraphTitle     :: String
  , miAlgName        :: String
  , miGenName        :: Either String String   -- | 'Left' means an input generator,
                                               --   'Right' a single input
  , evalMod          :: Maybe EvalMod
  , graphRanges      :: (Range a, Range b)
  , buildOptions     :: String
  , exeOptions       :: String
  }

instance (Show a, Real a, Show b, Real b) => Show (MetaInfo a b) where
    show = showMetaInfo

showMetaInfo mi = foldr (\x y -> x ++ "\n" ++ y) "" lines
  where
    lines  = map ("#" ++) lines'
    lines' =    map ("header: " ++) (header mi)
             ++ ["SBench version: " ++ sbenchVersion mi]
             ++ ["graph title: " ++ toWord (miGraphTitle mi)]
             ++ ["tested algorithm: " ++ toWord (miAlgName mi)]
             ++ inputOrInputGen (miGenName mi)
             ++ ["evaluation mode: " ++ showEvalMod (evalMod mi)]
             ++ ["graph ranges: " ++ showGraphRanges (graphRanges mi)]
             ++ ["build options: " ++ toWord (buildOptions mi)]
             ++ ["execution options: " ++ toWord (exeOptions mi)]
    showGraphRanges             = showPairWith showGraphRange showGraphRange
    showAxisLabels              = showListWith toWord
    showListWith  p xs          = "[" ++ showListWith' p xs ++ "]"
    showListWith' p []          = ""
    showListWith' p [x]         = p x
    showListWith' p (x:xs)      = p x ++ ", " ++ showListWith' p xs
    showPairWith s1 s2 (x, y)   = "(" ++ s1 x ++ ", " ++ s2 y ++ ")"
    showGraphRange AutoRange    = "Auto"
    showGraphRange (ManRange p) = show p
    toWord s                    = "\"" ++ s ++ "\""
    showEvalMod (Just evm)      = show evm
    showEvalMod Nothing         = "unknown"
    inputOrInputGen (Left gen)  = ["input generator: " ++ toWord gen]
    inputOrInputGen (Right inp) = ["input: " ++ toWord inp]  

data (Real a) => Range a = AutoRange | ManRange (a, a)