module Jobs.Types
  ( Job(..), Notification(..)
  , JobCtl(..)
  , JobContext(..)
  ) where

import Import.NoFoundation

import Data.Aeson (defaultOptions, Options(..), SumEncoding(..))
import Data.Aeson.TH (deriveJSON)

import Data.List.NonEmpty (NonEmpty)


data Job = JobSendNotification { jRecipient :: UserId, jNotification :: Notification }
         | JobSendTestEmail { jEmail :: Email, jMailContext :: MailContext }
         | JobQueueNotification { jNotification :: Notification }
         | JobHelpRequest { jSender :: Either (Maybe Address) UserId
                          , jRequestTime :: UTCTime
                          , jHelpRequest :: Text, jReferer :: Maybe Text }
         | JobSetLogSettings { jInstance :: InstanceId, jLogSettings :: LogSettings }         
         | JobDistributeCorrections { jSheet :: SheetId }
  deriving (Eq, Ord, Show, Read, Generic, Typeable)
data Notification = NotificationSubmissionRated { nSubmission :: SubmissionId }
                  | NotificationSheetActive { nSheet :: SheetId }
                  | NotificationSheetSoonInactive { nSheet :: SheetId }
                  | NotificationSheetInactive { nSheet :: SheetId }
                  | NotificationCorrectionsAssigned { nUser :: UserId, nSheet :: SheetId }
                  | NotificationCorrectionsNotDistributed { nSheet :: SheetId }
  deriving (Eq, Ord, Show, Read, Generic, Typeable)

instance Hashable Job
instance Hashable Notification

deriveJSON defaultOptions
  { constructorTagModifier = intercalate "-" . map toLower . drop 1 . splitCamel
  , fieldLabelModifier = intercalate "-" . map toLower . drop 1 . splitCamel
  , tagSingleConstructors = True
  , sumEncoding = TaggedObject "job" "data"
  } ''Job

deriveJSON defaultOptions
  { constructorTagModifier = intercalate "-" . map toLower . drop 1 . splitCamel
  , fieldLabelModifier = intercalate "-" . map toLower . drop 1 . splitCamel
  , tagSingleConstructors = True
  , sumEncoding = TaggedObject "notification" "data"
  } ''Notification


data JobCtl = JobCtlFlush
            | JobCtlPerform QueuedJobId
            | JobCtlDetermineCrontab
            | JobCtlQueue Job
  deriving (Eq, Ord, Read, Show, Generic, Typeable)

instance Hashable JobCtl


data JobContext = JobContext
  { jobCrontab :: TMVar (Crontab JobCtl)
  , jobConfirm :: TVar (HashMap JobCtl (NonEmpty (TMVar (Maybe SomeException))))
  }
