-- |  Little Brother data representation
module LiBro.Data where

import LiBro.Data.SafeText
import Data.Tree
import Data.Function
import Data.Map (Map)
import qualified Data.Map as M
import Data.Aeson
import GHC.Generics
import Data.Csv

-- |  A person that is assigned to 'Task's.
data Person = Person
  { Person -> Int
pid   :: Int
  , Person -> SafeText
name  :: SafeText
  , Person -> SafeText
email :: SafeText
  } deriving (Int -> Person -> ShowS
[Person] -> ShowS
Person -> String
(Int -> Person -> ShowS)
-> (Person -> String) -> ([Person] -> ShowS) -> Show Person
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Person -> ShowS
showsPrec :: Int -> Person -> ShowS
$cshow :: Person -> String
show :: Person -> String
$cshowList :: [Person] -> ShowS
showList :: [Person] -> ShowS
Show, (forall x. Person -> Rep Person x)
-> (forall x. Rep Person x -> Person) -> Generic Person
forall x. Rep Person x -> Person
forall x. Person -> Rep Person x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Person -> Rep Person x
from :: forall x. Person -> Rep Person x
$cto :: forall x. Rep Person x -> Person
to :: forall x. Rep Person x -> Person
Generic)

instance Eq Person where == :: Person -> Person -> Bool
(==) = Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Int -> Int -> Bool) -> (Person -> Int) -> Person -> Person -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Person -> Int
pid
instance Ord Person where <= :: Person -> Person -> Bool
(<=) = Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
(<=) (Int -> Int -> Bool) -> (Person -> Int) -> Person -> Person -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Person -> Int
pid
instance ToJSON Person
instance FromJSON Person
instance FromNamedRecord Person
instance DefaultOrdered Person
instance ToNamedRecord Person

-- |  'Person' container as a lookup table with person ID index.
type Persons = Map Int Person

-- |  Helper function to create a persons container.
personMap :: [Person] -> Persons
personMap :: [Person] -> Persons
personMap = [(Int, Person)] -> Persons
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(Int, Person)] -> Persons)
-> ([Person] -> [(Int, Person)]) -> [Person] -> Persons
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Person -> (Int, Person)) -> [Person] -> [(Int, Person)]
forall a b. (a -> b) -> [a] -> [b]
map ((,) (Int -> Person -> (Int, Person))
-> (Person -> Int) -> Person -> (Int, Person)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Person -> Int
pid)

-- |  Internal task representation.
data Task = Task
  { Task -> Int
tid         :: Int
  , Task -> SafeText
title       :: SafeText
  , Task -> SafeText
description :: SafeText
  , Task -> [Person]
assignees   :: [Person]
  } deriving (Int -> Task -> ShowS
[Task] -> ShowS
Task -> String
(Int -> Task -> ShowS)
-> (Task -> String) -> ([Task] -> ShowS) -> Show Task
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Task -> ShowS
showsPrec :: Int -> Task -> ShowS
$cshow :: Task -> String
show :: Task -> String
$cshowList :: [Task] -> ShowS
showList :: [Task] -> ShowS
Show, (forall x. Task -> Rep Task x)
-> (forall x. Rep Task x -> Task) -> Generic Task
forall x. Rep Task x -> Task
forall x. Task -> Rep Task x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Task -> Rep Task x
from :: forall x. Task -> Rep Task x
$cto :: forall x. Rep Task x -> Task
to :: forall x. Rep Task x -> Task
Generic)

instance Eq Task where == :: Task -> Task -> Bool
(==) = Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Int -> Int -> Bool) -> (Task -> Int) -> Task -> Task -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Task -> Int
tid
instance Ord Task where <= :: Task -> Task -> Bool
(<=) = Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
(<=) (Int -> Int -> Bool) -> (Task -> Int) -> Task -> Task -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Task -> Int
tid
instance ToJSON Task
instance FromJSON Task

-- |  The primary data type for tasks, 'Tree's of 'Task'.
type Tasks = Forest Task

-- |  Find all 'Task's assigned to a given 'Person'.
assignedTasks :: Person -> Tasks -> [Task]
assignedTasks :: Person -> Tasks -> [Task]
assignedTasks Person
p = (Task -> Bool) -> [Task] -> [Task]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Person
p Person -> [Person] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem`) ([Person] -> Bool) -> (Task -> [Person]) -> Task -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Task -> [Person]
assignees) ([Task] -> [Task]) -> (Tasks -> [Task]) -> Tasks -> [Task]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Tree Task -> [Task]) -> Tasks -> [Task]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Tree Task -> [Task]
forall a. Tree a -> [a]
flatten

-- |  Complete LiBro state in one type
data LiBroData = LBS
  { LiBroData -> Persons
persons :: Persons
  , LiBroData -> Tasks
tasks   :: Tasks
  } deriving (LiBroData -> LiBroData -> Bool
(LiBroData -> LiBroData -> Bool)
-> (LiBroData -> LiBroData -> Bool) -> Eq LiBroData
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: LiBroData -> LiBroData -> Bool
== :: LiBroData -> LiBroData -> Bool
$c/= :: LiBroData -> LiBroData -> Bool
/= :: LiBroData -> LiBroData -> Bool
Eq, Int -> LiBroData -> ShowS
[LiBroData] -> ShowS
LiBroData -> String
(Int -> LiBroData -> ShowS)
-> (LiBroData -> String)
-> ([LiBroData] -> ShowS)
-> Show LiBroData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LiBroData -> ShowS
showsPrec :: Int -> LiBroData -> ShowS
$cshow :: LiBroData -> String
show :: LiBroData -> String
$cshowList :: [LiBroData] -> ShowS
showList :: [LiBroData] -> ShowS
Show)