module Database.Schema.Migrations.Filesystem.Serialize
    ( serializeMigration
    )
where

import Data.Time () -- for UTCTime Show instance
import Data.Maybe ( catMaybes )
import Data.List ( intercalate )

import Database.Schema.Migrations.Migration
    ( Migration(..)
    )

type FieldSerializer = Migration -> Maybe String

fieldSerializers :: [FieldSerializer]
fieldSerializers = [ serializeDesc
                   , serializeTimestamp
                   , serializeDepends
                   , serializeApply
                   , serializeRevert
                   ]

serializeDesc :: FieldSerializer
serializeDesc m =
    case mDesc m of
      Nothing -> Nothing
      Just desc -> Just $ "Description: " ++ desc

serializeTimestamp :: FieldSerializer
serializeTimestamp m = Just $ "Created: " ++ (show $ mTimestamp m)

serializeDepends :: FieldSerializer
serializeDepends m = Just $ "Depends: " ++ (intercalate " " $ mDeps m)

serializeRevert :: FieldSerializer
serializeRevert m =
    case mRevert m of
      Nothing -> Nothing
      Just revert -> Just $ "Revert: |\n" ++
                     (serializeMultiline revert)

serializeApply :: FieldSerializer
serializeApply m = Just $ "Apply: |\n" ++ (serializeMultiline $ mApply m)

commonPrefix :: String -> String -> String
commonPrefix a b = map fst $ takeWhile (uncurry (==)) (zip a b)

commonPrefixLines :: [String] -> String
commonPrefixLines [] = ""
commonPrefixLines theLines = foldl1 commonPrefix theLines

serializeMultiline :: String -> String
serializeMultiline s =
    let sLines = lines s
        prefix = case commonPrefixLines sLines of
                   -- If the lines already have a common prefix that
                   -- begins with whitespace, no new prefix is
                   -- necessary.
                   (' ':_) -> ""
                   -- Otherwise, use a new prefix of two spaces.
                   _ -> "  "

    in unlines $ map (prefix ++) sLines

serializeMigration :: Migration -> String
serializeMigration m = intercalate "\n" fields
    where
      fields = catMaybes [ f m | f <- fieldSerializers ]