module Elm
    ( ToElm (..)
    , Options (..)
    , Expr (..)
    , Primitive (..)
    , Generator (..)
    , defaultOptions
    , genericToElm
    , generateElm
    ) where

import           Data.List
import           Data.List.Split
import           Elm.Decoder
import           Elm.Encoder
import           Elm.Helpers
import           Elm.Record
import           Elm.Types
import           System.Directory
import           System.FilePath

imports :: [(Expr, [Generator])] -> [String]
imports inclusions = map toImport $ ti ++ di ++ ei
    where generators = concat $ map snd inclusions
          ti = if Type `elem` generators
               then [ ("Date", Just "Date")
                    ]
               else []
          di = if Decoder `elem` generators || ListDecoder `elem` generators
               then [ ("Json.Decode", Just "(:=)")
                    , ("Json.Decode.Extra", Just "(|:)")
                    ]
               else []
          ei = if Encoder `elem` generators
               then [ ("Json.Encode", Nothing)
                    , ("Date.Format", Nothing)
                    ]
               else []
          toImport (moduleName, Nothing) = "import " ++ moduleName
          toImport (moduleName, Just exp) = "import " ++ moduleName ++ " exposing (" ++ exp ++ ")"

generate :: Generator -> Expr -> String
generate Type = record
generate SumType = sumType
generate Decoder = decoder
generate ListDecoder = listDecoder
generate Encoder = encoder

generateElm :: FilePath -> String -> [String] -> [(Expr, [Generator])] -> IO ()
generateElm destination moduleName customImports inclusions = do
    createDirectoryIfMissing True directory
    writeFile filePath fileBody
    putStrLn $ "Generated: " ++ filePath
    where namespace = "module " ++ moduleName ++ " exposing (..)"
          extraImports = map (\i -> "import " ++ i ++ " exposing (..)") customImports
          allImports = format $ imports inclusions ++ extraImports
          definitions = map (\(e, gs) -> format $ pad $ map (flip generate e) gs) inclusions
          pad = intersperse "\n"
          fileBody = format $ pad $ filter (not . null) $
              namespace : allImports : definitions
          filePath = intercalate "/" (filter (not . null) $ destination : splitOn "." moduleName) ++ ".elm"
          directory = takeDirectory filePath