{-# LANGUAGE BangPatterns              #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE GADTs                     #-}

module Experimenter.Availability.Type where

import           Control.DeepSeq
import           Data.Conduit
import           Database.Esqueleto  as E
import           Experimenter.Models

import           Experimenter.DB

data Availability m b
  = Available !b
  | AvailableOnDemand !(DB m b)

instance (Show b) => Show (Availability m b) where
  show :: Availability m b -> String
show (Available b
b)         = b -> String
forall a. Show a => a -> String
show b
b
  show (AvailableOnDemand DB m b
_) = String
"Available on demand"

instance (NFData b) => NFData (Availability m b) where
  rnf :: Availability m b -> ()
rnf (Available b
b)          = b -> ()
forall a. NFData a => a -> ()
rnf b
b
  rnf (AvailableOnDemand !DB m b
_) = ()


type AggregateFunction = E.SqlExpr (E.Value Double) -> E.SqlExpr (E.Value (Maybe Double))


data AvailabilityListWhere
  = GetAll
  | PrepInputWhere     !(E.SqlExpr (Entity PrepInput)     -> E.SqlExpr (Entity PrepInputValue)   -> E.SqlQuery ())
  | WarmUpInputWhere   !(E.SqlExpr (Entity WarmUpInput)   -> E.SqlExpr (Entity WarmUpInputValue) -> E.SqlQuery ())
  | RepInputWhere      !(E.SqlExpr (Entity RepInput)      -> E.SqlExpr (Entity RepInputValue)    -> E.SqlQuery ())
  | PrepMeasureWhere   !(E.SqlExpr (Entity PrepMeasure)   -> E.SqlExpr (Entity PrepResultStep)   -> E.SqlQuery ())
  | WarmUpMeasureWhere !(E.SqlExpr (Entity WarmUpMeasure) -> E.SqlExpr (Entity WarmUpResultStep) -> E.SqlQuery ())
  | RepMeasureWhere    !(E.SqlExpr (Entity RepMeasure)    -> E.SqlExpr (Entity RepResultStep)    -> E.SqlQuery ())


instance Show AvailabilityListWhere where
  show :: AvailabilityListWhere -> String
show GetAll{}             = String
"GetAll"
  show PrepInputWhere{}     = String
"PrepInputWhere"
  show WarmUpInputWhere{}   = String
"WarmUpInputWhere"
  show RepInputWhere{}      = String
"RepInputWhere"
  show PrepMeasureWhere{}   = String
"PrepMeasureWhere"
  show WarmUpMeasureWhere{} = String
"WarmUpMeasureWhere"
  show RepMeasureWhere{}    = String
"RepMeasureWhere"


data AvailabilityList m b
  = AvailableList !(Int, [b]) (AvailabilityListWhere -> ConduitT () b (DB m) ())
  | AvailableListOnDemand (Int, AvailabilityListWhere -> ConduitT () b (DB m) ())


instance (Show b) => Show (AvailabilityList m b) where
  show :: AvailabilityList m b -> String
show (AvailableList (Int, [b])
b AvailabilityListWhere -> ConduitT () b (DB m) ()
_)       = (Int, [b]) -> String
forall a. Show a => a -> String
show (Int, [b])
b
  show (AvailableListOnDemand (Int, AvailabilityListWhere -> ConduitT () b (DB m) ())
_) = String
"AvailableList on demand"

instance (NFData b) => NFData (AvailabilityList m b) where
  rnf :: AvailabilityList m b -> ()
rnf (AvailableList (Int, [b])
b AvailabilityListWhere -> ConduitT () b (DB m) ()
_)            = (Int, [b]) -> ()
forall a. NFData a => a -> ()
rnf (Int, [b])
b
  rnf (AvailableListOnDemand (Int
nr,AvailabilityListWhere -> ConduitT () b (DB m) ()
_)) = Int -> ()
forall a. NFData a => a -> ()
rnf Int
nr