{-|
Module      : Hasklepias Event accessors
Description : Methods fro accessing data in events.
Copyright   : (c) NoviSci, Inc 2020
License     : BSD3
Maintainer  : bsaul@novisci.com
-}
{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE NoImplicitPrelude #-}

module EventData.Accessors
  ( viewBirthYears
  , viewGenders
  , viewStates
  , previewDemoInfo
  , previewBirthYear
  ) where

import           Control.Lens                   ( (^.)
                                                , preview
                                                )
import           Control.Monad                  ( (=<<)
                                                , Functor(fmap)
                                                )
import           Data.Either                    ( either )
import           Data.Foldable                  ( toList )
import           Data.Function                  ( ($)
                                                , (.)
                                                , const
                                                )
import           Data.Functor.Contravariant     ( Predicate(..) )
import           Data.Maybe                     ( Maybe(..) )
import           Data.Ord                       ( Ord )
import           Data.Text                      ( Text )
import           Data.Text.Read                 ( rational )
import           Data.Time.Calendar             ( Day
                                                , DayOfMonth
                                                , MonthOfYear
                                                , Year
                                                , diffDays
                                                , toGregorian
                                                )
import           Data.Tuple                     ( fst )
import           EventData.Context              ( Concepts
                                                , Context(..)
                                                , Source
                                                , facts
                                                , hasConcepts
                                                )
import           EventData.Context.Domain       ( Domain
                                                , _Demographics
                                                , demo
                                                , info
                                                )
import           EventData.Core                 ( Event
                                                , ctxt
                                                )
import           EventData.Predicates           ( isBirthYearEvent
                                                , isGenderFactEvent
                                                , isStateFactEvent
                                                )
import           GHC.Num                        ( Integer
                                                , fromInteger
                                                )
import           GHC.Real                       ( RealFrac(floor) )
import           Witherable                     ( Filterable(filter, mapMaybe)
                                                , Witherable
                                                )

-- | Preview demographics information from a domain
previewDemoInfo :: Domain -> Maybe Text
previewDemoInfo :: Domain -> Maybe Text
previewDemoInfo Domain
dmn = (DemographicsFacts
-> Getting (Maybe Text) DemographicsFacts (Maybe Text)
-> Maybe Text
forall s a. s -> Getting a s a -> a
^. (DemographicsInfo -> Const (Maybe Text) DemographicsInfo)
-> DemographicsFacts -> Const (Maybe Text) DemographicsFacts
Iso' DemographicsFacts DemographicsInfo
demo ((DemographicsInfo -> Const (Maybe Text) DemographicsInfo)
 -> DemographicsFacts -> Const (Maybe Text) DemographicsFacts)
-> ((Maybe Text -> Const (Maybe Text) (Maybe Text))
    -> DemographicsInfo -> Const (Maybe Text) DemographicsInfo)
-> Getting (Maybe Text) DemographicsFacts (Maybe Text)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Text -> Const (Maybe Text) (Maybe Text))
-> DemographicsInfo -> Const (Maybe Text) DemographicsInfo
Lens' DemographicsInfo (Maybe Text)
info) (DemographicsFacts -> Maybe Text)
-> Maybe DemographicsFacts -> Maybe Text
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Getting (First DemographicsFacts) Domain DemographicsFacts
-> Domain -> Maybe DemographicsFacts
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview Getting (First DemographicsFacts) Domain DemographicsFacts
Prism' Domain DemographicsFacts
_Demographics Domain
dmn

-- | Utility for reading text into a maybe integer
intMayMap :: Text -> Maybe Integer -- TODO: this is ridiculous
intMayMap :: Text -> Maybe Integer
intMayMap Text
x =
  (Double -> Integer) -> Maybe Double -> Maybe Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
floor ((String -> Maybe Double)
-> ((Double, Text) -> Maybe Double)
-> Either String (Double, Text)
-> Maybe Double
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe Double -> String -> Maybe Double
forall a b. a -> b -> a
const Maybe Double
forall a. Maybe a
Nothing) (Double -> Maybe Double
forall a. a -> Maybe a
Just (Double -> Maybe Double)
-> ((Double, Text) -> Double) -> (Double, Text) -> Maybe Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Double, Text) -> Double
forall a b. (a, b) -> a
fst) (Reader Double
forall a. Fractional a => Reader a
Data.Text.Read.rational Text
x))

-- | Preview birth year from a domain
previewBirthYear :: Domain -> Maybe Year
previewBirthYear :: Domain -> Maybe Integer
previewBirthYear Domain
dmn = Text -> Maybe Integer
intMayMap (Text -> Maybe Integer) -> Maybe Text -> Maybe Integer
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Domain -> Maybe Text
previewDemoInfo Domain
dmn

-- | Returns a (possibly empty) list of birth years from a set of events
viewBirthYears :: (Witherable f) => f (Event a) -> [Year]
viewBirthYears :: f (Event a) -> [Integer]
viewBirthYears f (Event a)
x = (Event a -> Maybe Integer) -> [Event a] -> [Integer]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe
  (\Event a
e -> Domain -> Maybe Integer
previewBirthYear (Domain -> Maybe Integer) -> Maybe Domain -> Maybe Integer
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Domain -> Maybe Domain
forall a. a -> Maybe a
Just (Event a -> Context
forall a. Event a -> Context
ctxt Event a
e Context -> Getting Domain Context Domain -> Domain
forall s a. s -> Getting a s a -> a
^. Getting Domain Context Domain
Lens' Context Domain
facts))
  (f (Event a) -> [Event a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (f (Event a) -> [Event a]) -> f (Event a) -> [Event a]
forall a b. (a -> b) -> a -> b
$ (Event a -> Bool) -> f (Event a) -> f (Event a)
forall (f :: * -> *) a. Filterable f => (a -> Bool) -> f a -> f a
filter (Predicate (Event a) -> Event a -> Bool
forall a. Predicate a -> a -> Bool
getPredicate Predicate (Event a)
forall a. Predicate (Event a)
isBirthYearEvent) f (Event a)
x)

-- | Returns a (possibly empty) list of Gender values from a set of events
viewGenders :: (Witherable f) => f (Event a) -> [Text]
viewGenders :: f (Event a) -> [Text]
viewGenders f (Event a)
x = (Event a -> Maybe Text) -> [Event a] -> [Text]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe (\Event a
e -> Domain -> Maybe Text
previewDemoInfo (Domain -> Maybe Text) -> Maybe Domain -> Maybe Text
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Domain -> Maybe Domain
forall a. a -> Maybe a
Just (Event a -> Context
forall a. Event a -> Context
ctxt Event a
e Context -> Getting Domain Context Domain -> Domain
forall s a. s -> Getting a s a -> a
^. Getting Domain Context Domain
Lens' Context Domain
facts))
                         (f (Event a) -> [Event a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (f (Event a) -> [Event a]) -> f (Event a) -> [Event a]
forall a b. (a -> b) -> a -> b
$ (Event a -> Bool) -> f (Event a) -> f (Event a)
forall (f :: * -> *) a. Filterable f => (a -> Bool) -> f a -> f a
filter (Predicate (Event a) -> Event a -> Bool
forall a. Predicate a -> a -> Bool
getPredicate Predicate (Event a)
forall a. Predicate (Event a)
isGenderFactEvent) f (Event a)
x)

-- | Returns a (possibly empty) list of Gender values from a set of events
viewStates :: (Witherable f) => f (Event a) -> [Text]
viewStates :: f (Event a) -> [Text]
viewStates f (Event a)
x = (Event a -> Maybe Text) -> [Event a] -> [Text]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe (\Event a
e -> Domain -> Maybe Text
previewDemoInfo (Domain -> Maybe Text) -> Maybe Domain -> Maybe Text
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Domain -> Maybe Domain
forall a. a -> Maybe a
Just (Event a -> Context
forall a. Event a -> Context
ctxt Event a
e Context -> Getting Domain Context Domain -> Domain
forall s a. s -> Getting a s a -> a
^. Getting Domain Context Domain
Lens' Context Domain
facts))
                        (f (Event a) -> [Event a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (f (Event a) -> [Event a]) -> f (Event a) -> [Event a]
forall a b. (a -> b) -> a -> b
$ (Event a -> Bool) -> f (Event a) -> f (Event a)
forall (f :: * -> *) a. Filterable f => (a -> Bool) -> f a -> f a
filter (Predicate (Event a) -> Event a -> Bool
forall a. Predicate a -> a -> Bool
getPredicate Predicate (Event a)
forall a. Predicate (Event a)
isStateFactEvent) f (Event a)
x)