-- | This module provides tweaks able to remove elements from collections
-- focused in a 'TxSkel'.
module Cooked.Tweak.Remove
  ( -- * Removing elements from lists
    removeIfTweak,
    removeAtPosTweak,

    -- * Removing elements from maps
    removeAtTweak,

    -- * Removing elements from sets
    removeInTweak,
  )
where

import Cooked.Skeleton
import Cooked.Tweak.Common
import Cooked.Tweak.Query
import Cooked.Tweak.Update
import Data.List (partition)
import Data.Map (Map)
import Data.Set (Set)
import Optics.Core
import Polysemy

-- | Removes elements satisfying a predicate from a list focused in a 'TxSkel',
-- returning the elements that were removed.
removeIfTweak ::
  ( Member Tweak effs,
    Is k A_Lens
  ) =>
  Optic' k is TxSkel [a] ->
  (a -> Bool) ->
  Sem effs [a]
removeIfTweak :: forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Lens) =>
Optic' k is TxSkel [a] -> (a -> Bool) -> Sem effs [a]
removeIfTweak (forall (destKind :: OpticKind) (srcKind :: OpticKind)
       (is :: IxList) (s :: OpticKind) (t :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Is srcKind destKind =>
Optic srcKind is s t a b -> Optic destKind is s t a b
castOptic @A_Lens -> Optic A_Lens is TxSkel TxSkel [a] [a]
optic) a -> Bool
removePred = do
  [a]
as <- Optic A_Lens is TxSkel TxSkel [a] [a] -> Sem effs [a]
forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Getter) =>
Optic' k is TxSkel a -> Sem effs a
viewTweak Optic A_Lens is TxSkel TxSkel [a] [a]
optic
  let ([a]
removed, [a]
kept) = (a -> Bool) -> [a] -> ([a], [a])
forall (a :: OpticKind). (a -> Bool) -> [a] -> ([a], [a])
partition a -> Bool
removePred [a]
as
  Optic A_Lens is TxSkel TxSkel [a] [a] -> [a] -> Sem effs ()
forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Setter) =>
Optic' k is TxSkel a -> a -> Sem effs ()
setTweak Optic A_Lens is TxSkel TxSkel [a] [a]
optic [a]
kept
  [a] -> Sem effs [a]
forall (a :: OpticKind). a -> Sem effs a
forall (m :: OpticKind -> OpticKind) (a :: OpticKind).
Monad m =>
a -> m a
return [a]
removed

-- | Removes an element at a specific position in a list focused in a
-- 'TxSkel', returning the removed element, if any.
removeAtPosTweak ::
  ( Member Tweak effs,
    Is k A_Lens
  ) =>
  Optic' k is TxSkel [a] ->
  Int ->
  Sem effs (Maybe a)
removeAtPosTweak :: forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Lens) =>
Optic' k is TxSkel [a] -> Int -> Sem effs (Maybe a)
removeAtPosTweak (forall (destKind :: OpticKind) (srcKind :: OpticKind)
       (is :: IxList) (s :: OpticKind) (t :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Is srcKind destKind =>
Optic srcKind is s t a b -> Optic destKind is s t a b
castOptic @A_Lens -> Optic A_Lens is TxSkel TxSkel [a] [a]
optic) Int
i = do
  [a]
as <- Optic A_Lens is TxSkel TxSkel [a] [a] -> Sem effs [a]
forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Getter) =>
Optic' k is TxSkel a -> Sem effs a
viewTweak Optic A_Lens is TxSkel TxSkel [a] [a]
optic
  let ([a]
before, [a]
after) = Int -> [a] -> ([a], [a])
forall (a :: OpticKind). Int -> [a] -> ([a], [a])
splitAt Int
i [a]
as
  case [a]
after of
    [] -> Maybe a -> Sem effs (Maybe a)
forall (a :: OpticKind). a -> Sem effs a
forall (m :: OpticKind -> OpticKind) (a :: OpticKind).
Monad m =>
a -> m a
return Maybe a
forall (a :: OpticKind). Maybe a
Nothing
    a
x : [a]
xs -> do
      Optic A_Lens is TxSkel TxSkel [a] [a] -> [a] -> Sem effs ()
forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Setter) =>
Optic' k is TxSkel a -> a -> Sem effs ()
setTweak Optic A_Lens is TxSkel TxSkel [a] [a]
optic ([a]
before [a] -> [a] -> [a]
forall (a :: OpticKind). [a] -> [a] -> [a]
++ [a]
xs)
      Maybe a -> Sem effs (Maybe a)
forall (a :: OpticKind). a -> Sem effs a
forall (m :: OpticKind -> OpticKind) (a :: OpticKind).
Monad m =>
a -> m a
return (Maybe a -> Sem effs (Maybe a)) -> Maybe a -> Sem effs (Maybe a)
forall (a :: OpticKind) b. (a -> b) -> a -> b
$ a -> Maybe a
forall (a :: OpticKind). a -> Maybe a
Just a
x

-- | Removes an element at a specific key in a map focused in a 'TxSkel',
-- returning the removed value, if any.
removeAtTweak ::
  ( Member Tweak effs,
    Is k A_Lens,
    Ord a
  ) =>
  Optic' k is TxSkel (Map a b) ->
  a ->
  Sem effs (Maybe b)
removeAtTweak :: forall (effs :: EffectRow) (k :: OpticKind) (a :: OpticKind)
       (is :: IxList) (b :: OpticKind).
(Member Tweak effs, Is k A_Lens, Ord a) =>
Optic' k is TxSkel (Map a b) -> a -> Sem effs (Maybe b)
removeAtTweak (forall (destKind :: OpticKind) (srcKind :: OpticKind)
       (is :: IxList) (s :: OpticKind) (t :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Is srcKind destKind =>
Optic srcKind is s t a b -> Optic destKind is s t a b
castOptic @A_Lens -> Optic A_Lens is TxSkel TxSkel (Map a b) (Map a b)
optic) a
a = do
  Maybe b
mb <- Optic' A_Lens is TxSkel (Maybe b) -> Sem effs (Maybe b)
forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Getter) =>
Optic' k is TxSkel a -> Sem effs a
viewTweak (Optic A_Lens is TxSkel TxSkel (Map a b) (Map a b)
optic Optic A_Lens is TxSkel TxSkel (Map a b) (Map a b)
-> Optic A_Lens NoIx (Map a b) (Map a b) (Maybe b) (Maybe b)
-> Optic' A_Lens is TxSkel (Maybe b)
forall (k :: OpticKind) (l :: OpticKind) (m :: OpticKind)
       (is :: IxList) (js :: IxList) (ks :: IxList) (s :: OpticKind)
       (t :: OpticKind) (u :: OpticKind) (v :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Index (Map a b) -> Lens' (Map a b) (Maybe (IxValue (Map a b)))
forall (m :: OpticKind).
At m =>
Index m -> Lens' m (Maybe (IxValue m))
at a
Index (Map a b)
a)
  Optic' A_Lens is TxSkel (Maybe b) -> Maybe b -> Sem effs ()
forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Setter) =>
Optic' k is TxSkel a -> a -> Sem effs ()
setTweak (Optic A_Lens is TxSkel TxSkel (Map a b) (Map a b)
optic Optic A_Lens is TxSkel TxSkel (Map a b) (Map a b)
-> Optic A_Lens NoIx (Map a b) (Map a b) (Maybe b) (Maybe b)
-> Optic' A_Lens is TxSkel (Maybe b)
forall (k :: OpticKind) (l :: OpticKind) (m :: OpticKind)
       (is :: IxList) (js :: IxList) (ks :: IxList) (s :: OpticKind)
       (t :: OpticKind) (u :: OpticKind) (v :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Index (Map a b) -> Lens' (Map a b) (Maybe (IxValue (Map a b)))
forall (m :: OpticKind).
At m =>
Index m -> Lens' m (Maybe (IxValue m))
at a
Index (Map a b)
a) Maybe b
forall (a :: OpticKind). Maybe a
Nothing
  Maybe b -> Sem effs (Maybe b)
forall (a :: OpticKind). a -> Sem effs a
forall (m :: OpticKind -> OpticKind) (a :: OpticKind).
Monad m =>
a -> m a
return Maybe b
mb

-- | Removes an element in a set focused in a 'TxSkel', returning the removed
-- value, if any.
removeInTweak ::
  ( Member Tweak effs,
    Is k A_Lens,
    Ord a
  ) =>
  Optic' k is TxSkel (Set a) ->
  a ->
  Sem effs (Maybe a)
removeInTweak :: forall (effs :: EffectRow) (k :: OpticKind) (a :: OpticKind)
       (is :: IxList).
(Member Tweak effs, Is k A_Lens, Ord a) =>
Optic' k is TxSkel (Set a) -> a -> Sem effs (Maybe a)
removeInTweak (forall (destKind :: OpticKind) (srcKind :: OpticKind)
       (is :: IxList) (s :: OpticKind) (t :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Is srcKind destKind =>
Optic srcKind is s t a b -> Optic destKind is s t a b
castOptic @A_Lens -> Optic A_Lens is TxSkel TxSkel (Set a) (Set a)
optic) a
a = do
  Maybe ()
mb <- Optic' A_Lens is TxSkel (Maybe ()) -> Sem effs (Maybe ())
forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Getter) =>
Optic' k is TxSkel a -> Sem effs a
viewTweak (Optic A_Lens is TxSkel TxSkel (Set a) (Set a)
optic Optic A_Lens is TxSkel TxSkel (Set a) (Set a)
-> Optic A_Lens NoIx (Set a) (Set a) (Maybe ()) (Maybe ())
-> Optic' A_Lens is TxSkel (Maybe ())
forall (k :: OpticKind) (l :: OpticKind) (m :: OpticKind)
       (is :: IxList) (js :: IxList) (ks :: IxList) (s :: OpticKind)
       (t :: OpticKind) (u :: OpticKind) (v :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Index (Set a) -> Lens' (Set a) (Maybe (IxValue (Set a)))
forall (m :: OpticKind).
At m =>
Index m -> Lens' m (Maybe (IxValue m))
at a
Index (Set a)
a)
  Optic' A_Lens is TxSkel (Maybe ()) -> Maybe () -> Sem effs ()
forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Setter) =>
Optic' k is TxSkel a -> a -> Sem effs ()
setTweak (Optic A_Lens is TxSkel TxSkel (Set a) (Set a)
optic Optic A_Lens is TxSkel TxSkel (Set a) (Set a)
-> Optic A_Lens NoIx (Set a) (Set a) (Maybe ()) (Maybe ())
-> Optic' A_Lens is TxSkel (Maybe ())
forall (k :: OpticKind) (l :: OpticKind) (m :: OpticKind)
       (is :: IxList) (js :: IxList) (ks :: IxList) (s :: OpticKind)
       (t :: OpticKind) (u :: OpticKind) (v :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Index (Set a) -> Lens' (Set a) (Maybe (IxValue (Set a)))
forall (m :: OpticKind).
At m =>
Index m -> Lens' m (Maybe (IxValue m))
at a
Index (Set a)
a) Maybe ()
forall (a :: OpticKind). Maybe a
Nothing
  Maybe a -> Sem effs (Maybe a)
forall (a :: OpticKind). a -> Sem effs a
forall (m :: OpticKind -> OpticKind) (a :: OpticKind).
Monad m =>
a -> m a
return (Maybe a -> Sem effs (Maybe a)) -> Maybe a -> Sem effs (Maybe a)
forall (a :: OpticKind) b. (a -> b) -> a -> b
$ a
a a -> Maybe () -> Maybe a
forall (a :: OpticKind) (b :: OpticKind). a -> Maybe b -> Maybe a
forall (f :: OpticKind -> OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Functor f =>
a -> f b -> f a
<$ Maybe ()
mb