{-# LANGUAGE TemplateHaskell     #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RecordWildCards     #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE TypeOperators       #-}
{-# LANGUAGE DeriveGeneric       #-}

module Speechmatics.JSON.PeekJob where

import           System.Exit        (exitFailure, exitSuccess)
import           System.IO          (stderr, hPutStrLn)
import qualified Data.ByteString.Lazy.Char8 as BSL
import           System.Environment (getArgs)
import           Control.Monad      (forM_, mzero, join)
import           Control.Applicative
import           Data.Aeson.AutoType.Alternative
import           Data.Aeson(decode, Value(..), FromJSON(..), ToJSON(..),
                            pairs, eitherDecode ,
                            (.:), (.:?), (.=), object)
import           Data.Monoid
import           Data.Text (Text)
import Data.Bifunctor
import qualified GHC.Generics

-- | Workaround for https://github.com/bos/aeson/issues/287.
o .:?? val = fmap join (o .:? val)

data Job = Job { 
    jobCheckWait :: (Maybe Integer),
    jobNotification :: Text,
    jobJobType :: Text,
    jobUrl :: Text,
    jobNextCheck :: Double,
    jobLang :: Text,
    jobJobStatus :: Text,
    jobName :: Text,
    jobCreatedAt :: Text,
    jobId :: Double,
    jobMeta :: (Maybe Value),
    jobUserId :: Double,
    jobDuration :: Double,
    jobTranscription :: Maybe Text
  } deriving (Show,Eq,GHC.Generics.Generic)


instance FromJSON Job where
  parseJSON (Object v) = Job <$> v .:?? "check_wait" <*> v .:   "notification" <*> v .:   "job_type" <*> v .:   "url" <*> v .:   "next_check" <*> v .:   "lang" <*> v .:   "job_status" <*> v .:   "name" <*> v .:   "created_at" <*> v .:   "id" <*> v .:?? "meta" <*> v .:   "user_id" <*> v .:   "duration" <*> v .:   "transcription"
  parseJSON _          = mzero


data TopLevel = TopLevel { 
    topLevelJob :: Job
  } deriving (Show,Eq,GHC.Generics.Generic)


instance FromJSON TopLevel where
  parseJSON (Object v) = TopLevel <$> v .:   "job"
  parseJSON _          = mzero

parse :: BSL.ByteString -> Either String Job
parse = (second topLevelJob)  -- get rid of toplevel
          . eitherDecode