{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE NoFieldSelectors #-}

module WikiMusic.Model.Thread
  ( Thread (..),
    ThreadRender (..),
    mkThreads,
    renderThread,
  )
where

import Data.Aeson
import Data.OpenApi
import Optics
import Relude

data Thread a = Thread a [Thread a]
  deriving (Thread a -> Thread a -> Bool
(Thread a -> Thread a -> Bool)
-> (Thread a -> Thread a -> Bool) -> Eq (Thread a)
forall a. Eq a => Thread a -> Thread a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Thread a -> Thread a -> Bool
== :: Thread a -> Thread a -> Bool
$c/= :: forall a. Eq a => Thread a -> Thread a -> Bool
/= :: Thread a -> Thread a -> Bool
Eq, Int -> Thread a -> ShowS
[Thread a] -> ShowS
Thread a -> String
(Int -> Thread a -> ShowS)
-> (Thread a -> String) -> ([Thread a] -> ShowS) -> Show (Thread a)
forall a. Show a => Int -> Thread a -> ShowS
forall a. Show a => [Thread a] -> ShowS
forall a. Show a => Thread a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Thread a -> ShowS
showsPrec :: Int -> Thread a -> ShowS
$cshow :: forall a. Show a => Thread a -> String
show :: Thread a -> String
$cshowList :: forall a. Show a => [Thread a] -> ShowS
showList :: [Thread a] -> ShowS
Show, (forall x. Thread a -> Rep (Thread a) x)
-> (forall x. Rep (Thread a) x -> Thread a) -> Generic (Thread a)
forall x. Rep (Thread a) x -> Thread a
forall x. Thread a -> Rep (Thread a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Thread a) x -> Thread a
forall a x. Thread a -> Rep (Thread a) x
$cfrom :: forall a x. Thread a -> Rep (Thread a) x
from :: forall x. Thread a -> Rep (Thread a) x
$cto :: forall a x. Rep (Thread a) x -> Thread a
to :: forall x. Rep (Thread a) x -> Thread a
Generic, Maybe (Thread a)
Value -> Parser [Thread a]
Value -> Parser (Thread a)
(Value -> Parser (Thread a))
-> (Value -> Parser [Thread a])
-> Maybe (Thread a)
-> FromJSON (Thread a)
forall a. FromJSON a => Maybe (Thread a)
forall a. FromJSON a => Value -> Parser [Thread a]
forall a. FromJSON a => Value -> Parser (Thread a)
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: forall a. FromJSON a => Value -> Parser (Thread a)
parseJSON :: Value -> Parser (Thread a)
$cparseJSONList :: forall a. FromJSON a => Value -> Parser [Thread a]
parseJSONList :: Value -> Parser [Thread a]
$comittedField :: forall a. FromJSON a => Maybe (Thread a)
omittedField :: Maybe (Thread a)
FromJSON, [Thread a] -> Value
[Thread a] -> Encoding
Thread a -> Bool
Thread a -> Value
Thread a -> Encoding
(Thread a -> Value)
-> (Thread a -> Encoding)
-> ([Thread a] -> Value)
-> ([Thread a] -> Encoding)
-> (Thread a -> Bool)
-> ToJSON (Thread a)
forall a. ToJSON a => [Thread a] -> Value
forall a. ToJSON a => [Thread a] -> Encoding
forall a. ToJSON a => Thread a -> Bool
forall a. ToJSON a => Thread a -> Value
forall a. ToJSON a => Thread a -> Encoding
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: forall a. ToJSON a => Thread a -> Value
toJSON :: Thread a -> Value
$ctoEncoding :: forall a. ToJSON a => Thread a -> Encoding
toEncoding :: Thread a -> Encoding
$ctoJSONList :: forall a. ToJSON a => [Thread a] -> Value
toJSONList :: [Thread a] -> Value
$ctoEncodingList :: forall a. ToJSON a => [Thread a] -> Encoding
toEncodingList :: [Thread a] -> Encoding
$comitField :: forall a. ToJSON a => Thread a -> Bool
omitField :: Thread a -> Bool
ToJSON)

data ThreadRender a = ThreadRender
  { forall a. ThreadRender a -> a
node :: a,
    forall a. ThreadRender a -> [ThreadRender a]
subNodes :: [ThreadRender a]
  }
  deriving (ThreadRender a -> ThreadRender a -> Bool
(ThreadRender a -> ThreadRender a -> Bool)
-> (ThreadRender a -> ThreadRender a -> Bool)
-> Eq (ThreadRender a)
forall a. Eq a => ThreadRender a -> ThreadRender a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => ThreadRender a -> ThreadRender a -> Bool
== :: ThreadRender a -> ThreadRender a -> Bool
$c/= :: forall a. Eq a => ThreadRender a -> ThreadRender a -> Bool
/= :: ThreadRender a -> ThreadRender a -> Bool
Eq, Int -> ThreadRender a -> ShowS
[ThreadRender a] -> ShowS
ThreadRender a -> String
(Int -> ThreadRender a -> ShowS)
-> (ThreadRender a -> String)
-> ([ThreadRender a] -> ShowS)
-> Show (ThreadRender a)
forall a. Show a => Int -> ThreadRender a -> ShowS
forall a. Show a => [ThreadRender a] -> ShowS
forall a. Show a => ThreadRender a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> ThreadRender a -> ShowS
showsPrec :: Int -> ThreadRender a -> ShowS
$cshow :: forall a. Show a => ThreadRender a -> String
show :: ThreadRender a -> String
$cshowList :: forall a. Show a => [ThreadRender a] -> ShowS
showList :: [ThreadRender a] -> ShowS
Show, (forall x. ThreadRender a -> Rep (ThreadRender a) x)
-> (forall x. Rep (ThreadRender a) x -> ThreadRender a)
-> Generic (ThreadRender a)
forall x. Rep (ThreadRender a) x -> ThreadRender a
forall x. ThreadRender a -> Rep (ThreadRender a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (ThreadRender a) x -> ThreadRender a
forall a x. ThreadRender a -> Rep (ThreadRender a) x
$cfrom :: forall a x. ThreadRender a -> Rep (ThreadRender a) x
from :: forall x. ThreadRender a -> Rep (ThreadRender a) x
$cto :: forall a x. Rep (ThreadRender a) x -> ThreadRender a
to :: forall x. Rep (ThreadRender a) x -> ThreadRender a
Generic, Maybe (ThreadRender a)
Value -> Parser [ThreadRender a]
Value -> Parser (ThreadRender a)
(Value -> Parser (ThreadRender a))
-> (Value -> Parser [ThreadRender a])
-> Maybe (ThreadRender a)
-> FromJSON (ThreadRender a)
forall a. FromJSON a => Maybe (ThreadRender a)
forall a. FromJSON a => Value -> Parser [ThreadRender a]
forall a. FromJSON a => Value -> Parser (ThreadRender a)
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: forall a. FromJSON a => Value -> Parser (ThreadRender a)
parseJSON :: Value -> Parser (ThreadRender a)
$cparseJSONList :: forall a. FromJSON a => Value -> Parser [ThreadRender a]
parseJSONList :: Value -> Parser [ThreadRender a]
$comittedField :: forall a. FromJSON a => Maybe (ThreadRender a)
omittedField :: Maybe (ThreadRender a)
FromJSON, [ThreadRender a] -> Value
[ThreadRender a] -> Encoding
ThreadRender a -> Bool
ThreadRender a -> Value
ThreadRender a -> Encoding
(ThreadRender a -> Value)
-> (ThreadRender a -> Encoding)
-> ([ThreadRender a] -> Value)
-> ([ThreadRender a] -> Encoding)
-> (ThreadRender a -> Bool)
-> ToJSON (ThreadRender a)
forall a. ToJSON a => [ThreadRender a] -> Value
forall a. ToJSON a => [ThreadRender a] -> Encoding
forall a. ToJSON a => ThreadRender a -> Bool
forall a. ToJSON a => ThreadRender a -> Value
forall a. ToJSON a => ThreadRender a -> Encoding
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: forall a. ToJSON a => ThreadRender a -> Value
toJSON :: ThreadRender a -> Value
$ctoEncoding :: forall a. ToJSON a => ThreadRender a -> Encoding
toEncoding :: ThreadRender a -> Encoding
$ctoJSONList :: forall a. ToJSON a => [ThreadRender a] -> Value
toJSONList :: [ThreadRender a] -> Value
$ctoEncodingList :: forall a. ToJSON a => [ThreadRender a] -> Encoding
toEncodingList :: [ThreadRender a] -> Encoding
$comitField :: forall a. ToJSON a => ThreadRender a -> Bool
omitField :: ThreadRender a -> Bool
ToJSON)

instance (ToSchema a) => ToSchema (ThreadRender a)

makeFieldLabelsNoPrefix ''Thread

renderThread :: Thread a -> ThreadRender a
renderThread :: forall a. Thread a -> ThreadRender a
renderThread (Thread a
x [Thread a]
xs) = do
  ThreadRender {$sel:node:ThreadRender :: a
node = a
x, $sel:subNodes:ThreadRender :: [ThreadRender a]
subNodes = (Thread a -> ThreadRender a) -> [Thread a] -> [ThreadRender a]
forall a b. (a -> b) -> [a] -> [b]
map Thread a -> ThreadRender a
forall a. Thread a -> ThreadRender a
renderThread [Thread a]
xs}

mkThreads :: [a] -> (a -> a -> Bool) -> (a -> Maybe b) -> [Thread a]
mkThreads :: forall a b. [a] -> (a -> a -> Bool) -> (a -> Maybe b) -> [Thread a]
mkThreads [a]
nodes a -> a -> Bool
isChildOf a -> Maybe b
getParentIdentifier = [Thread a] -> [Thread a]
filterRootNodes ([Thread a] -> [Thread a]) -> [Thread a] -> [Thread a]
forall a b. (a -> b) -> a -> b
$ (a -> Thread a) -> [a] -> [Thread a]
forall a b. (a -> b) -> [a] -> [b]
map a -> Thread a
withThreadChildren [a]
nodes
  where
    directChildren :: a -> [a]
directChildren a
node = (a -> Bool) -> [a] -> [a]
forall a. (a -> Bool) -> [a] -> [a]
filter (a -> a -> Bool
isChildOf a
node) [a]
nodes
    withThreadChildren :: a -> Thread a
withThreadChildren a
node = a -> [Thread a] -> Thread a
forall a. a -> [Thread a] -> Thread a
Thread a
node ([Thread a] -> Thread a) -> [Thread a] -> Thread a
forall a b. (a -> b) -> a -> b
$ (a -> Thread a) -> [a] -> [Thread a]
forall a b. (a -> b) -> [a] -> [b]
map a -> Thread a
withThreadChildren (a -> [a]
directChildren a
node)
    filterRootNodes :: [Thread a] -> [Thread a]
filterRootNodes = (Thread a -> Bool) -> [Thread a] -> [Thread a]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(Thread a
x [Thread a]
_) -> Maybe b -> Bool
forall a. Maybe a -> Bool
isNothing (a -> Maybe b
getParentIdentifier a
x))