{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveFoldable #-}
module Text.Layout.Table.Spec.RowGroup where

import Text.Layout.Table.Spec.Util

import Data.List (transpose)
import Data.Functor (void)

-- | Groups rows together which should not be visually seperated from each other.
data RowGroup a
    = SingletonRowGroup (Row a)
    | MultiRowGroup [Row a]
    | NullableRowGroup [Row (Maybe a)]

-- | Group the given rows together.
rowsG :: [Row a] -> RowGroup a
rowsG :: forall a. [Row a] -> RowGroup a
rowsG = [Row a] -> RowGroup a
forall a. [Row a] -> RowGroup a
MultiRowGroup

-- | Make a group of a single row.
rowG :: Row a -> RowGroup a
rowG :: forall a. Row a -> RowGroup a
rowG = Row a -> RowGroup a
forall a. Row a -> RowGroup a
SingletonRowGroup

-- | Provide a 'RowGroup' where single cells may be missing.
nullableRowsG :: [Row (Maybe a)] -> RowGroup a
nullableRowsG :: forall a. [Row (Maybe a)] -> RowGroup a
nullableRowsG = [Row (Maybe a)] -> RowGroup a
forall a. [Row (Maybe a)] -> RowGroup a
NullableRowGroup

-- | Extracts the shape of the 'RowGroup' from the first row.
rowGroupShape :: RowGroup a -> [()]
rowGroupShape :: forall a. RowGroup a -> [()]
rowGroupShape RowGroup a
rg = case RowGroup a
rg of
    SingletonRowGroup Row a
r  -> Row a -> [()]
forall (f :: * -> *) a. Functor f => f a -> f ()
void Row a
r
    MultiRowGroup [Row a]
rs     -> [Row a] -> [()]
forall {a}. [[a]] -> [()]
firstSubListShape [Row a]
rs
    NullableRowGroup [Row (Maybe a)]
ors -> [Row (Maybe a)] -> [()]
forall {a}. [[a]] -> [()]
firstSubListShape [Row (Maybe a)]
ors
  where
    firstSubListShape :: [[a]] -> [()]
firstSubListShape [[a]]
l = case [[a]]
l of
        [a]
r : [[a]]
_ -> [a] -> [()]
forall (f :: * -> *) a. Functor f => f a -> f ()
void [a]
r
        []    -> []

data ColumnSegment a
    = SingleValueSegment a
    | ColumnSegment (Col a)
    | NullableColumnSegment (Col (Maybe a))
    deriving ((forall a b. (a -> b) -> ColumnSegment a -> ColumnSegment b)
-> (forall a b. a -> ColumnSegment b -> ColumnSegment a)
-> Functor ColumnSegment
forall a b. a -> ColumnSegment b -> ColumnSegment a
forall a b. (a -> b) -> ColumnSegment a -> ColumnSegment b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> ColumnSegment b -> ColumnSegment a
$c<$ :: forall a b. a -> ColumnSegment b -> ColumnSegment a
fmap :: forall a b. (a -> b) -> ColumnSegment a -> ColumnSegment b
$cfmap :: forall a b. (a -> b) -> ColumnSegment a -> ColumnSegment b
Functor, (forall m. Monoid m => ColumnSegment m -> m)
-> (forall m a. Monoid m => (a -> m) -> ColumnSegment a -> m)
-> (forall m a. Monoid m => (a -> m) -> ColumnSegment a -> m)
-> (forall a b. (a -> b -> b) -> b -> ColumnSegment a -> b)
-> (forall a b. (a -> b -> b) -> b -> ColumnSegment a -> b)
-> (forall b a. (b -> a -> b) -> b -> ColumnSegment a -> b)
-> (forall b a. (b -> a -> b) -> b -> ColumnSegment a -> b)
-> (forall a. (a -> a -> a) -> ColumnSegment a -> a)
-> (forall a. (a -> a -> a) -> ColumnSegment a -> a)
-> (forall a. ColumnSegment a -> [a])
-> (forall a. ColumnSegment a -> Bool)
-> (forall a. ColumnSegment a -> Int)
-> (forall a. Eq a => a -> ColumnSegment a -> Bool)
-> (forall a. Ord a => ColumnSegment a -> a)
-> (forall a. Ord a => ColumnSegment a -> a)
-> (forall a. Num a => ColumnSegment a -> a)
-> (forall a. Num a => ColumnSegment a -> a)
-> Foldable ColumnSegment
forall a. Eq a => a -> ColumnSegment a -> Bool
forall a. Num a => ColumnSegment a -> a
forall a. Ord a => ColumnSegment a -> a
forall m. Monoid m => ColumnSegment m -> m
forall a. ColumnSegment a -> Bool
forall a. ColumnSegment a -> Int
forall a. ColumnSegment a -> [a]
forall a. (a -> a -> a) -> ColumnSegment a -> a
forall m a. Monoid m => (a -> m) -> ColumnSegment a -> m
forall b a. (b -> a -> b) -> b -> ColumnSegment a -> b
forall a b. (a -> b -> b) -> b -> ColumnSegment a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: forall a. Num a => ColumnSegment a -> a
$cproduct :: forall a. Num a => ColumnSegment a -> a
sum :: forall a. Num a => ColumnSegment a -> a
$csum :: forall a. Num a => ColumnSegment a -> a
minimum :: forall a. Ord a => ColumnSegment a -> a
$cminimum :: forall a. Ord a => ColumnSegment a -> a
maximum :: forall a. Ord a => ColumnSegment a -> a
$cmaximum :: forall a. Ord a => ColumnSegment a -> a
elem :: forall a. Eq a => a -> ColumnSegment a -> Bool
$celem :: forall a. Eq a => a -> ColumnSegment a -> Bool
length :: forall a. ColumnSegment a -> Int
$clength :: forall a. ColumnSegment a -> Int
null :: forall a. ColumnSegment a -> Bool
$cnull :: forall a. ColumnSegment a -> Bool
toList :: forall a. ColumnSegment a -> [a]
$ctoList :: forall a. ColumnSegment a -> [a]
foldl1 :: forall a. (a -> a -> a) -> ColumnSegment a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> ColumnSegment a -> a
foldr1 :: forall a. (a -> a -> a) -> ColumnSegment a -> a
$cfoldr1 :: forall a. (a -> a -> a) -> ColumnSegment a -> a
foldl' :: forall b a. (b -> a -> b) -> b -> ColumnSegment a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> ColumnSegment a -> b
foldl :: forall b a. (b -> a -> b) -> b -> ColumnSegment a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> ColumnSegment a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> ColumnSegment a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> ColumnSegment a -> b
foldr :: forall a b. (a -> b -> b) -> b -> ColumnSegment a -> b
$cfoldr :: forall a b. (a -> b -> b) -> b -> ColumnSegment a -> b
foldMap' :: forall m a. Monoid m => (a -> m) -> ColumnSegment a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> ColumnSegment a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> ColumnSegment a -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> ColumnSegment a -> m
fold :: forall m. Monoid m => ColumnSegment m -> m
$cfold :: forall m. Monoid m => ColumnSegment m -> m
Foldable, ColumnSegment a -> ColumnSegment a -> Bool
(ColumnSegment a -> ColumnSegment a -> Bool)
-> (ColumnSegment a -> ColumnSegment a -> Bool)
-> Eq (ColumnSegment a)
forall a. Eq a => ColumnSegment a -> ColumnSegment a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ColumnSegment a -> ColumnSegment a -> Bool
$c/= :: forall a. Eq a => ColumnSegment a -> ColumnSegment a -> Bool
== :: ColumnSegment a -> ColumnSegment a -> Bool
$c== :: forall a. Eq a => ColumnSegment a -> ColumnSegment a -> Bool
Eq, Int -> ColumnSegment a -> ShowS
[ColumnSegment a] -> ShowS
ColumnSegment a -> String
(Int -> ColumnSegment a -> ShowS)
-> (ColumnSegment a -> String)
-> ([ColumnSegment a] -> ShowS)
-> Show (ColumnSegment a)
forall a. Show a => Int -> ColumnSegment a -> ShowS
forall a. Show a => [ColumnSegment a] -> ShowS
forall a. Show a => ColumnSegment a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ColumnSegment a] -> ShowS
$cshowList :: forall a. Show a => [ColumnSegment a] -> ShowS
show :: ColumnSegment a -> String
$cshow :: forall a. Show a => ColumnSegment a -> String
showsPrec :: Int -> ColumnSegment a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> ColumnSegment a -> ShowS
Show)

newtype SegmentedColumn a = SegmentedColumn [ColumnSegment a] deriving ((forall a b. (a -> b) -> SegmentedColumn a -> SegmentedColumn b)
-> (forall a b. a -> SegmentedColumn b -> SegmentedColumn a)
-> Functor SegmentedColumn
forall a b. a -> SegmentedColumn b -> SegmentedColumn a
forall a b. (a -> b) -> SegmentedColumn a -> SegmentedColumn b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> SegmentedColumn b -> SegmentedColumn a
$c<$ :: forall a b. a -> SegmentedColumn b -> SegmentedColumn a
fmap :: forall a b. (a -> b) -> SegmentedColumn a -> SegmentedColumn b
$cfmap :: forall a b. (a -> b) -> SegmentedColumn a -> SegmentedColumn b
Functor, (forall m. Monoid m => SegmentedColumn m -> m)
-> (forall m a. Monoid m => (a -> m) -> SegmentedColumn a -> m)
-> (forall m a. Monoid m => (a -> m) -> SegmentedColumn a -> m)
-> (forall a b. (a -> b -> b) -> b -> SegmentedColumn a -> b)
-> (forall a b. (a -> b -> b) -> b -> SegmentedColumn a -> b)
-> (forall b a. (b -> a -> b) -> b -> SegmentedColumn a -> b)
-> (forall b a. (b -> a -> b) -> b -> SegmentedColumn a -> b)
-> (forall a. (a -> a -> a) -> SegmentedColumn a -> a)
-> (forall a. (a -> a -> a) -> SegmentedColumn a -> a)
-> (forall a. SegmentedColumn a -> [a])
-> (forall a. SegmentedColumn a -> Bool)
-> (forall a. SegmentedColumn a -> Int)
-> (forall a. Eq a => a -> SegmentedColumn a -> Bool)
-> (forall a. Ord a => SegmentedColumn a -> a)
-> (forall a. Ord a => SegmentedColumn a -> a)
-> (forall a. Num a => SegmentedColumn a -> a)
-> (forall a. Num a => SegmentedColumn a -> a)
-> Foldable SegmentedColumn
forall a. Eq a => a -> SegmentedColumn a -> Bool
forall a. Num a => SegmentedColumn a -> a
forall a. Ord a => SegmentedColumn a -> a
forall m. Monoid m => SegmentedColumn m -> m
forall a. SegmentedColumn a -> Bool
forall a. SegmentedColumn a -> Int
forall a. SegmentedColumn a -> [a]
forall a. (a -> a -> a) -> SegmentedColumn a -> a
forall m a. Monoid m => (a -> m) -> SegmentedColumn a -> m
forall b a. (b -> a -> b) -> b -> SegmentedColumn a -> b
forall a b. (a -> b -> b) -> b -> SegmentedColumn a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: forall a. Num a => SegmentedColumn a -> a
$cproduct :: forall a. Num a => SegmentedColumn a -> a
sum :: forall a. Num a => SegmentedColumn a -> a
$csum :: forall a. Num a => SegmentedColumn a -> a
minimum :: forall a. Ord a => SegmentedColumn a -> a
$cminimum :: forall a. Ord a => SegmentedColumn a -> a
maximum :: forall a. Ord a => SegmentedColumn a -> a
$cmaximum :: forall a. Ord a => SegmentedColumn a -> a
elem :: forall a. Eq a => a -> SegmentedColumn a -> Bool
$celem :: forall a. Eq a => a -> SegmentedColumn a -> Bool
length :: forall a. SegmentedColumn a -> Int
$clength :: forall a. SegmentedColumn a -> Int
null :: forall a. SegmentedColumn a -> Bool
$cnull :: forall a. SegmentedColumn a -> Bool
toList :: forall a. SegmentedColumn a -> [a]
$ctoList :: forall a. SegmentedColumn a -> [a]
foldl1 :: forall a. (a -> a -> a) -> SegmentedColumn a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> SegmentedColumn a -> a
foldr1 :: forall a. (a -> a -> a) -> SegmentedColumn a -> a
$cfoldr1 :: forall a. (a -> a -> a) -> SegmentedColumn a -> a
foldl' :: forall b a. (b -> a -> b) -> b -> SegmentedColumn a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> SegmentedColumn a -> b
foldl :: forall b a. (b -> a -> b) -> b -> SegmentedColumn a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> SegmentedColumn a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> SegmentedColumn a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> SegmentedColumn a -> b
foldr :: forall a b. (a -> b -> b) -> b -> SegmentedColumn a -> b
$cfoldr :: forall a b. (a -> b -> b) -> b -> SegmentedColumn a -> b
foldMap' :: forall m a. Monoid m => (a -> m) -> SegmentedColumn a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> SegmentedColumn a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> SegmentedColumn a -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> SegmentedColumn a -> m
fold :: forall m. Monoid m => SegmentedColumn m -> m
$cfold :: forall m. Monoid m => SegmentedColumn m -> m
Foldable, SegmentedColumn a -> SegmentedColumn a -> Bool
(SegmentedColumn a -> SegmentedColumn a -> Bool)
-> (SegmentedColumn a -> SegmentedColumn a -> Bool)
-> Eq (SegmentedColumn a)
forall a. Eq a => SegmentedColumn a -> SegmentedColumn a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SegmentedColumn a -> SegmentedColumn a -> Bool
$c/= :: forall a. Eq a => SegmentedColumn a -> SegmentedColumn a -> Bool
== :: SegmentedColumn a -> SegmentedColumn a -> Bool
$c== :: forall a. Eq a => SegmentedColumn a -> SegmentedColumn a -> Bool
Eq, Int -> SegmentedColumn a -> ShowS
[SegmentedColumn a] -> ShowS
SegmentedColumn a -> String
(Int -> SegmentedColumn a -> ShowS)
-> (SegmentedColumn a -> String)
-> ([SegmentedColumn a] -> ShowS)
-> Show (SegmentedColumn a)
forall a. Show a => Int -> SegmentedColumn a -> ShowS
forall a. Show a => [SegmentedColumn a] -> ShowS
forall a. Show a => SegmentedColumn a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SegmentedColumn a] -> ShowS
$cshowList :: forall a. Show a => [SegmentedColumn a] -> ShowS
show :: SegmentedColumn a -> String
$cshow :: forall a. Show a => SegmentedColumn a -> String
showsPrec :: Int -> SegmentedColumn a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> SegmentedColumn a -> ShowS
Show)

-- | Break down several 'RowGroups', which conceptually form a column by
-- themselves, into a list of columns.
transposeRowGroups :: Col (RowGroup a) -> [SegmentedColumn a]
transposeRowGroups :: forall a. Col (RowGroup a) -> [SegmentedColumn a]
transposeRowGroups = ([ColumnSegment a] -> SegmentedColumn a)
-> [[ColumnSegment a]] -> [SegmentedColumn a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [ColumnSegment a] -> SegmentedColumn a
forall a. [ColumnSegment a] -> SegmentedColumn a
SegmentedColumn ([[ColumnSegment a]] -> [SegmentedColumn a])
-> ([RowGroup a] -> [[ColumnSegment a]])
-> [RowGroup a]
-> [SegmentedColumn a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[ColumnSegment a]] -> [[ColumnSegment a]]
forall a. [[a]] -> [[a]]
transpose ([[ColumnSegment a]] -> [[ColumnSegment a]])
-> ([RowGroup a] -> [[ColumnSegment a]])
-> [RowGroup a]
-> [[ColumnSegment a]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (RowGroup a -> [ColumnSegment a])
-> [RowGroup a] -> [[ColumnSegment a]]
forall a b. (a -> b) -> [a] -> [b]
map RowGroup a -> [ColumnSegment a]
forall a. RowGroup a -> [ColumnSegment a]
transposeRowGroup
  where
    transposeRowGroup :: RowGroup a -> [ColumnSegment a]
    transposeRowGroup :: forall a. RowGroup a -> [ColumnSegment a]
transposeRowGroup RowGroup a
rg = case RowGroup a
rg of
        SingletonRowGroup Row a
row -> a -> ColumnSegment a
forall a. a -> ColumnSegment a
SingleValueSegment (a -> ColumnSegment a) -> Row a -> [ColumnSegment a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Row a
row
        MultiRowGroup [Row a]
rows    -> Row a -> ColumnSegment a
forall a. Col a -> ColumnSegment a
ColumnSegment (Row a -> ColumnSegment a) -> [Row a] -> [ColumnSegment a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Row a] -> [Row a]
forall a. [[a]] -> [[a]]
transpose [Row a]
rows
        NullableRowGroup [Row (Maybe a)]
rows -> Row (Maybe a) -> ColumnSegment a
forall a. Col (Maybe a) -> ColumnSegment a
NullableColumnSegment (Row (Maybe a) -> ColumnSegment a)
-> [Row (Maybe a)] -> [ColumnSegment a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Row (Maybe a)] -> [Row (Maybe a)]
forall a. [[a]] -> [[a]]
transpose [Row (Maybe a)]
rows

-- | Map each column with the corresponding function and replace empty inputs
-- with the given value.
mapRowGroupColumns :: [(b, a -> b)] -> RowGroup a -> [[b]]
mapRowGroupColumns :: forall b a. [(b, a -> b)] -> RowGroup a -> [[b]]
mapRowGroupColumns [(b, a -> b)]
mappers RowGroup a
rg = case RowGroup a
rg of
    SingletonRowGroup Row a
row  -> [b] -> [[b]]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([b] -> [[b]]) -> [b] -> [[b]]
forall a b. (a -> b) -> a -> b
$ ((b, a -> b) -> a -> b) -> [(b, a -> b)] -> Row a -> [b]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (b, a -> b) -> a -> b
forall a b. (a, b) -> b
snd [(b, a -> b)]
mappers Row a
row
    MultiRowGroup [Row a]
rows     -> ((b, a -> b) -> a -> b) -> [Row a] -> [[b]]
forall {b} {c}. ((b, a -> b) -> b -> c) -> [[b]] -> [[c]]
mapGrid (b, a -> b) -> a -> b
forall a b. (a, b) -> b
snd [Row a]
rows
    NullableRowGroup [Row (Maybe a)]
orows -> ((b, a -> b) -> Maybe a -> b) -> [Row (Maybe a)] -> [[b]]
forall {b} {c}. ((b, a -> b) -> b -> c) -> [[b]] -> [[c]]
mapGrid ((b -> (a -> b) -> Maybe a -> b) -> (b, a -> b) -> Maybe a -> b
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry b -> (a -> b) -> Maybe a -> b
forall b a. b -> (a -> b) -> Maybe a -> b
maybe) [Row (Maybe a)]
orows
  where
    mapGrid :: ((b, a -> b) -> b -> c) -> [[b]] -> [[c]]
mapGrid (b, a -> b) -> b -> c
applyMapper = ([b] -> [c]) -> [[b]] -> [[c]]
forall a b. (a -> b) -> [a] -> [b]
map (([b] -> [c]) -> [[b]] -> [[c]]) -> ([b] -> [c]) -> [[b]] -> [[c]]
forall a b. (a -> b) -> a -> b
$ ((b, a -> b) -> b -> c) -> [(b, a -> b)] -> [b] -> [c]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (b, a -> b) -> b -> c
applyMapper [(b, a -> b)]
mappers