-- |
--
-- Copyright   : (C) Keera Studios Ltd, 2013
-- License     : BSD3
-- Maintainer  : support@keera.co.uk
module Hails.MVC.Model.ReactiveFields where

import Hails.MVC.Model.ReactiveModel

-- The following code presents a possibly simpler way of creating reactive
-- fields in a reactive model.
type Field a b c = (b -> a, a -> b -> Bool, a -> b -> b, c)

preTrue :: a -> b -> Bool
preTrue :: a -> b -> Bool
preTrue = (b -> Bool) -> a -> b -> Bool
forall a b. a -> b -> a
const ((b -> Bool) -> a -> b -> Bool) -> (b -> Bool) -> a -> b -> Bool
forall a b. (a -> b) -> a -> b
$ Bool -> b -> Bool
forall a b. a -> b -> a
const Bool
True

fieldSetter :: (Eq a, Event c)
            => Field a b c -> ReactiveModel b c d -> a -> ReactiveModel b c d
fieldSetter :: Field a b c -> ReactiveModel b c d -> a -> ReactiveModel b c d
fieldSetter f :: Field a b c
f@(b -> a
_, a -> b -> Bool
pre, a -> b -> b
rSet, c
ev) ReactiveModel b c d
rm a
newVal
  | Field a b c -> ReactiveModel b c d -> a
forall c a b d. Event c => Field a b c -> ReactiveModel b c d -> a
fieldGetter Field a b c
f ReactiveModel b c d
rm a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
newVal       = ReactiveModel b c d
rm
  | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ a -> b -> Bool
pre a
newVal (b -> Bool) -> b -> Bool
forall a b. (a -> b) -> a -> b
$ ReactiveModel b c d -> b
forall a b c. Event b => ReactiveModel a b c -> a
basicModel ReactiveModel b c d
rm = ReactiveModel b c d -> c -> ReactiveModel b c d
forall b a c.
Event b =>
ReactiveModel a b c -> b -> ReactiveModel a b c
triggerEvent ReactiveModel b c d
rm c
ev
  | Bool
otherwise                        = ReactiveModel b c d -> c -> ReactiveModel b c d
forall b a c.
Event b =>
ReactiveModel a b c -> b -> ReactiveModel a b c
triggerEvent ReactiveModel b c d
rm' c
ev
 where rm' :: ReactiveModel b c d
rm' = ReactiveModel b c d
rm ReactiveModel b c d -> (b -> b) -> ReactiveModel b c d
forall b a c.
Event b =>
ReactiveModel a b c -> (a -> a) -> ReactiveModel a b c
`onBasicModel` a -> b -> b
rSet a
newVal

fieldGetter :: (Event c) => Field a b c -> ReactiveModel b c d -> a
fieldGetter :: Field a b c -> ReactiveModel b c d -> a
fieldGetter (b -> a
rGet,a -> b -> Bool
_,a -> b -> b
_,c
_) = b -> a
rGet (b -> a) -> (ReactiveModel b c d -> b) -> ReactiveModel b c d -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReactiveModel b c d -> b
forall a b c. Event b => ReactiveModel a b c -> a
basicModel

fieldSetterUndo :: (Eq a, Event c)
                => Field a b c -> ReactiveModel b c d -> a -> ReactiveModel b c d
fieldSetterUndo :: Field a b c -> ReactiveModel b c d -> a -> ReactiveModel b c d
fieldSetterUndo f :: Field a b c
f@(b -> a
_, a -> b -> Bool
pre, a -> b -> b
rSet, c
ev) ReactiveModel b c d
rm a
newVal
  | Field a b c -> ReactiveModel b c d -> a
forall c a b d. Event c => Field a b c -> ReactiveModel b c d -> a
fieldGetter Field a b c
f ReactiveModel b c d
rm a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
newVal       = ReactiveModel b c d
rm
  | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ a -> b -> Bool
pre a
newVal (b -> Bool) -> b -> Bool
forall a b. (a -> b) -> a -> b
$ ReactiveModel b c d -> b
forall a b c. Event b => ReactiveModel a b c -> a
basicModel ReactiveModel b c d
rm = ReactiveModel b c d -> c -> ReactiveModel b c d
forall b a c.
Event b =>
ReactiveModel a b c -> b -> ReactiveModel a b c
triggerEvent ReactiveModel b c d
rm c
ev
  | Bool
otherwise                        = ReactiveModel b c d -> c -> ReactiveModel b c d
forall b a c.
Event b =>
ReactiveModel a b c -> b -> ReactiveModel a b c
triggerEvent ReactiveModel b c d
rm' c
ev
 where rm' :: ReactiveModel b c d
rm' = ReactiveModel b c d -> (b -> b) -> [c] -> ReactiveModel b c d
forall b a c.
Event b =>
ReactiveModel a b c -> (a -> a) -> [b] -> ReactiveModel a b c
recordChange ReactiveModel b c d
rm (a -> b -> b
rSet a
newVal) [c
ev]