{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Web.Geek.Config where

import Air.Env hiding (mod)
import Air.Extra
import Air.Spec
import Air.TH (here)
import Data.Aeson.Encode.Pretty (encodePretty)
import Data.Aeson.Generic (decode)
import Data.Aeson.Generic (toJSON)
import Data.Time
import System.Directory (doesFileExist)
import System.Environment (getArgs)
import System.Exit (exitWith, ExitCode(..))
import System.Locale (defaultTimeLocale)
import Test.Hspec
import Text.Printf
import Web.Geek.DefaultConfig
import Web.Geek.Type
import qualified Data.ByteString.Char8 as B
import qualified Data.Text.IO as TextIO
import System.Process (readProcess)


default_config_string :: String
default_config_string = b2u - B.unpack - l2s - encodePretty - toJSON default_config

parse_config :: B.ByteString -> Maybe Config
parse_config = s2l > decode

read_config_from_path :: FilePath -> IO (Maybe Config)
read_config_from_path _path = do
  _config <- readProcess ("." / _path) [] ""
  
  return - _config.u2b.B.pack.parse_config



geek_usage :: String
geek_usage = [here|

  Usage: geek $GEEK_CONFIG_GENERATOR (default: geek-config.hs)

|]


get_config_from_args :: IO Config
get_config_from_args = do
  let default_config_path = "blog/geek-config.hs"
  
  _args <- getArgs
  
  let 
    usage = do
      puts geek_usage
      exitWith (ExitFailure 1)
  
  
  _path <-
      case _args of
        [] -> return default_config_path
        [x] -> return x
        _ -> do
          puts - "Invalid number of arguments: " + show _args
          usage

  _path_exist <- doesFileExist _path
  
  maybe_config <- 
    if not _path_exist
      then do
        puts - printf "Warning: %s does not exist!" _path
        puts ""
        puts - "Fall back to Geek default configuration."
        return - parse_config (default_config_string.u2b.B.pack)
      
      else do      
        read_config_from_path _path
    
  case maybe_config of
    Nothing -> do
      puts - "Failed to parse the output of: " + _path
      puts ""
      puts - "Example:"
      puts - (20 :: Int).times '-'
      puts ""
      puts default_config_string
      puts ""
  
      exitWith (ExitFailure 1)
  
    Just _config -> do
      puts ""
      TextIO.putStrLn - pretty_print_config _config
      puts ""
      return _config


post_date_length :: String -> Integer
post_date_length format = length - formatTime defaultTimeLocale format (def :: UTCTime)

spec :: Spec
spec = do
  describe "Config" - do
    it "should get date length" - do
      post_date_length "%Y-%m-%d-" === 11