module Codec.Sarsi.SBT.Machine where

import Codec.Sarsi (Event (..), Level (..), Message (..))
import Codec.Sarsi.Curses (cleaningCurses)
import Codec.Sarsi.SBT (SBTEvent (..), cleaningCursesSBT, eventParser)
import Data.Attoparsec.Text.Machine (asLines, processParser, streamParser)
import Data.Machine (ProcessT, asParts, auto, filtered, scan, (<~))
import Data.Text (Text)
import qualified Data.Text as Text

eventProcess :: Monad m => ProcessT m Text Event
eventProcess :: ProcessT m Text Event
eventProcess = MachineT m (Is [Event]) Event
forall (f :: * -> *) a. Foldable f => Process (f a) a
asParts MachineT m (Is [Event]) Event
-> MachineT m (Is Text) [Event] -> ProcessT m Text Event
forall (m :: * -> *) b c (k :: * -> *).
Monad m =>
ProcessT m b c -> MachineT m k b -> MachineT m k c
<~ ((Session, Maybe Event) -> [Event])
-> Process (Session, Maybe Event) [Event]
forall (k :: * -> * -> *) a b. Automaton k => k a b -> Process a b
auto (Session, Maybe Event) -> [Event]
forall a a. (a, Maybe a) -> [a]
unpack MachineT m (Is (Session, Maybe Event)) [Event]
-> MachineT m (Is Text) (Session, Maybe Event)
-> MachineT m (Is Text) [Event]
forall (m :: * -> *) b c (k :: * -> *).
Monad m =>
ProcessT m b c -> MachineT m k b -> MachineT m k c
<~ (((Session, Maybe Event) -> SBTEvent -> (Session, Maybe Event))
-> (Session, Maybe Event)
-> Machine (Is SBTEvent) (Session, Maybe Event)
forall (k :: * -> * -> *) a b.
Category k =>
(a -> b -> a) -> a -> Machine (k b) a
scan (Session, Maybe Event) -> SBTEvent -> (Session, Maybe Event)
forall b. (Session, b) -> SBTEvent -> (Session, Maybe Event)
f (Session
emptySession, Maybe Event
forall a. Maybe a
Nothing)) MachineT m (Is SBTEvent) (Session, Maybe Event)
-> MachineT m (Is Text) SBTEvent
-> MachineT m (Is Text) (Session, Maybe Event)
forall (m :: * -> *) b c (k :: * -> *).
Monad m =>
ProcessT m b c -> MachineT m k b -> MachineT m k c
<~ MachineT m (Is Text) SBTEvent
forall (m :: * -> *). Monad m => ProcessT m Text SBTEvent
eventProcess'
  where
    f :: (Session, b) -> SBTEvent -> (Session, Maybe Event)
f (Session
session, b
_) SBTEvent
event = Session -> SBTEvent -> (Session, Maybe Event)
runSession Session
session SBTEvent
event
    unpack :: (a, Maybe a) -> [a]
unpack (a
_, Just a
e) = [a
e]
    unpack (a, Maybe a)
_ = []

eventProcess' :: Monad m => ProcessT m Text SBTEvent
eventProcess' :: ProcessT m Text SBTEvent
eventProcess' = MachineT m (Is [SBTEvent]) SBTEvent
forall (f :: * -> *) a. Foldable f => Process (f a) a
asParts MachineT m (Is [SBTEvent]) SBTEvent
-> MachineT m (Is Text) [SBTEvent] -> ProcessT m Text SBTEvent
forall (m :: * -> *) b c (k :: * -> *).
Monad m =>
ProcessT m b c -> MachineT m k b -> MachineT m k c
<~ (Either String SBTEvent -> [SBTEvent])
-> Process (Either String SBTEvent) [SBTEvent]
forall (k :: * -> * -> *) a b. Automaton k => k a b -> Process a b
auto Either String SBTEvent -> [SBTEvent]
forall a a. Either a a -> [a]
unpackEvent MachineT m (Is (Either String SBTEvent)) [SBTEvent]
-> MachineT m (Is Text) (Either String SBTEvent)
-> MachineT m (Is Text) [SBTEvent]
forall (m :: * -> *) b c (k :: * -> *).
Monad m =>
ProcessT m b c -> MachineT m k b -> MachineT m k c
<~ Parser SBTEvent -> MachineT m (Is Text) (Either String SBTEvent)
forall (m :: * -> *) a.
Monad m =>
Parser a -> ProcessT m Text (Either String a)
streamParser Parser SBTEvent
eventParser MachineT m (Is Text) (Either String SBTEvent)
-> MachineT m (Is Text) Text
-> MachineT m (Is Text) (Either String SBTEvent)
forall (m :: * -> *) b c (k :: * -> *).
Monad m =>
ProcessT m b c -> MachineT m k b -> MachineT m k c
<~ MachineT m (Is Text) Text
preprocessing
  where
    preprocessing :: MachineT m (Is Text) Text
preprocessing = (Text -> Bool) -> Process Text Text
forall a. (a -> Bool) -> Process a a
filtered (Bool -> Bool
not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Bool
Text.null) MachineT m (Is Text) Text
-> MachineT m (Is Text) Text -> MachineT m (Is Text) Text
forall (m :: * -> *) b c (k :: * -> *).
Monad m =>
ProcessT m b c -> MachineT m k b -> MachineT m k c
<~ Parser Text -> MachineT m (Is Text) Text
forall (m :: * -> *) a.
Monad m =>
Parser a -> MachineT m (Is Text) a
parsing Parser Text
cleaningCursesSBT MachineT m (Is Text) Text
-> MachineT m (Is Text) Text -> MachineT m (Is Text) Text
forall (m :: * -> *) b c (k :: * -> *).
Monad m =>
ProcessT m b c -> MachineT m k b -> MachineT m k c
<~ Parser Text -> MachineT m (Is Text) Text
forall (m :: * -> *) a.
Monad m =>
Parser a -> MachineT m (Is Text) a
parsing Parser Text
cleaningCurses MachineT m (Is Text) Text
-> MachineT m (Is Text) Text -> MachineT m (Is Text) Text
forall (m :: * -> *) b c (k :: * -> *).
Monad m =>
ProcessT m b c -> MachineT m k b -> MachineT m k c
<~ MachineT m (Is Text) Text
input
      where
        input :: MachineT m (Is Text) Text
input = (Text -> Text) -> Process Text Text
forall (k :: * -> * -> *) a b. Automaton k => k a b -> Process a b
auto (\Text
txt -> Text -> Char -> Text
Text.snoc Text
txt Char
'\n') MachineT m (Is Text) Text
-> MachineT m (Is Text) Text -> MachineT m (Is Text) Text
forall (m :: * -> *) b c (k :: * -> *).
Monad m =>
ProcessT m b c -> MachineT m k b -> MachineT m k c
<~ MachineT m (Is Text) Text
Process Text Text
asLines
        parsing :: Parser a -> MachineT m (Is Text) a
parsing Parser a
p = MachineT m (Is [a]) a
forall (f :: * -> *) a. Foldable f => Process (f a) a
asParts MachineT m (Is [a]) a
-> MachineT m (Is Text) [a] -> MachineT m (Is Text) a
forall (m :: * -> *) b c (k :: * -> *).
Monad m =>
ProcessT m b c -> MachineT m k b -> MachineT m k c
<~ (Either String (Text, a) -> [a])
-> Process (Either String (Text, a)) [a]
forall (k :: * -> * -> *) a b. Automaton k => k a b -> Process a b
auto Either String (Text, a) -> [a]
forall a a a. Either a (a, a) -> [a]
f MachineT m (Is (Either String (Text, a))) [a]
-> MachineT m (Is Text) (Either String (Text, a))
-> MachineT m (Is Text) [a]
forall (m :: * -> *) b c (k :: * -> *).
Monad m =>
ProcessT m b c -> MachineT m k b -> MachineT m k c
<~ Parser a -> MachineT m (Is Text) (Either String (Text, a))
forall (m :: * -> *) a.
Monad m =>
Parser a -> ProcessT m Text (Either String (Text, a))
processParser Parser a
p
          where
            f :: Either a (a, a) -> [a]
f (Left a
_) = []
            f (Right (a
_, a
txt)) = [a
txt]
    unpackEvent :: Either a a -> [a]
unpackEvent (Right a
e) = [a
e]
    unpackEvent (Left a
_) = []

data Session = Session {Session -> Bool
isBuilding :: Bool, Session -> (Int, Int)
counts :: (Int, Int)}
  deriving (Int -> Session -> ShowS
[Session] -> ShowS
Session -> String
(Int -> Session -> ShowS)
-> (Session -> String) -> ([Session] -> ShowS) -> Show Session
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Session] -> ShowS
$cshowList :: [Session] -> ShowS
show :: Session -> String
$cshow :: Session -> String
showsPrec :: Int -> Session -> ShowS
$cshowsPrec :: Int -> Session -> ShowS
Show)

emptySession :: Session
emptySession :: Session
emptySession = Bool -> (Int, Int) -> Session
Session Bool
False (Int
0, Int
0)

runSession :: Session -> SBTEvent -> (Session, Maybe Event)
runSession :: Session -> SBTEvent -> (Session, Maybe Event)
runSession (Session Bool
False (Int, Int)
f) (CompileStart Text
_) = (Bool -> (Int, Int) -> Session
Session Bool
True (Int, Int)
f, Event -> Maybe Event
forall a. a -> Maybe a
Just (Event -> Maybe Event) -> Event -> Maybe Event
forall a b. (a -> b) -> a -> b
$ Text -> Event
Start (Text -> Event) -> Text -> Event
forall a b. (a -> b) -> a -> b
$ String -> Text
Text.pack String
"scala")
runSession (Session Bool
False (Int, Int)
f) SBTEvent
_ = (Bool -> (Int, Int) -> Session
Session Bool
False (Int, Int)
f, Maybe Event
forall a. Maybe a
Nothing)
runSession (Session Bool
True (Int, Int)
f) (CompileStart Text
_) = (Bool -> (Int, Int) -> Session
Session Bool
True (Int, Int)
f, Maybe Event
forall a. Maybe a
Nothing)
runSession (Session Bool
True (Int
e, Int
w)) (TaskFinish Bool
_ Text
_) = (Bool -> (Int, Int) -> Session
Session Bool
False (Int
0, Int
0), Event -> Maybe Event
forall a. a -> Maybe a
Just (Event -> Maybe Event) -> Event -> Maybe Event
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Event
Finish Int
e Int
w)
runSession (Session Bool
True (Int, Int)
f) (Throw Message
msg) = (Bool -> (Int, Int) -> Session
Session Bool
True (Message -> (Int, Int) -> (Int, Int)
forall b a. (Num b, Num a) => Message -> (a, b) -> (a, b)
inc Message
msg (Int, Int)
f), Event -> Maybe Event
forall a. a -> Maybe a
Just (Event -> Maybe Event) -> Event -> Maybe Event
forall a b. (a -> b) -> a -> b
$ Message -> Event
Notify Message
msg)
  where
    inc :: Message -> (a, b) -> (a, b)
inc (Message Location
_ Level
Warning [Text]
_) (a
e, b
w) = (a
e, b
w b -> b -> b
forall a. Num a => a -> a -> a
+ b
1)
    inc (Message Location
_ Level
Error [Text]
_) (a
e, b
w) = (a
e a -> a -> a
forall a. Num a => a -> a -> a
+ a
1, b
w)