{- |
some queries implemented using operations from relational algebra
-}
module Example.RelationalAlgebra where

import Query
import Company

import qualified Data.Map as Map
import Data.Maybe (isNothing, )
import qualified Data.Tree as Tree


{- |
all employees
-}
employees :: [Emp]
employees = emp

{-
Exercise:
Show all departments
-}

{- |
all clerks
-}
clerks :: [Emp]
clerks =
   filter (\e -> job e == Clerk) emp

{-
Exercise:
Show all clerks and analysts (intermixed)
-}

{- |
all clerks with salary at least 1000
-}
richClerks :: [Emp]
richClerks =
   filter (\e -> job e == Clerk && sal e >= 1000) emp

{-
Exercise:
Rewrite the above query without (&&).
-}

{- |
all employees in research department
-}
researchers :: [Emp]
researchers =
   map fst
      (filter (\(e,d) -> deptno e == deptno d && dname d == "RESEARCH")
         (cross emp dept))

{-
Exercise:
Write a natural join over Emp and Dept.
Result type shall be [(Emp,Dept)].
-}

researchers0 :: [Emp]
researchers0 =
   map snd
      (filter (\(d,e) -> deptno e == deptno d)
         (cross (filter (\d -> dname d == "RESEARCH") dept) emp))


hierarchy :: Tree.Forest Emp
hierarchy =
   let emptrees =
          map (\e -> Tree.Node e (filter ((Just (empno e) ==) . mgr . Tree.rootLabel) emptrees)) emp
   in  filter (isNothing . mgr . Tree.rootLabel) emptrees
{-
putStr $ Tree.drawForest $ map (fmap ename) hierarchy
-}

hierarchyFast :: Tree.Forest Emp
hierarchyFast =
   let emptrees =
          Map.fromListWith (++) $
          map
             (\e -> (mgr e, [Tree.Node e (Map.findWithDefault [] (Just (empno e)) emptrees)]))
             emp
   in  Map.findWithDefault [] Nothing emptrees


{- |
A recursive query:
Compute the total salary for each manager
and the total set of employees he conducts.
-}
teamSalaries :: [(String, Int)]
teamSalaries =
   let recurse (Tree.Node e sub0) =
          let sub1 = map recurse sub0
          in  Tree.Node (ename e, sal e + sum (map (snd . Tree.rootLabel) sub1)) sub1
   in  Tree.flatten =<< map recurse hierarchyFast
