module Runner.Example (
  Result (..)
, mkResult
) where

import           Data.Char
import           Util

data Result = Equal | NotEqual [String]
  deriving (Eq, Show)

mkResult :: [String] -> [String] -> Result
mkResult expected_ actual_
  | expected == actual = Equal
  | otherwise = NotEqual (formatNotEqual expected actual)
  where
    expected = map stripEnd expected_
    actual   = map stripEnd actual_

formatNotEqual :: [String] -> [String] -> [String]
formatNotEqual expected actual = formatLines "expected: " expected ++ formatLines " but got: " actual
  where
    -- use show to escape special characters in output lines if any output line
    -- contains any unsafe character
    escapeOutput
      | any (not . isSafe) (concat $ expected ++ actual) = map show
      | otherwise = id

    isSafe :: Char -> Bool
    isSafe c = c == ' ' || (isPrint c && (not . isSpace) c)

    formatLines :: String -> [String] -> [String]
    formatLines message xs = case escapeOutput xs of
      y:ys -> (message ++ y) : map (padding ++) ys
      []   -> [message]
      where
        padding = replicate (length message) ' '