-- | Plugin to change how many sections can be selected at once.
module Development.NSIS.Plugins.Sections(atMostOneSection, exactlyOneSection) where

import Control.Monad
import Development.NSIS


atMostOneSection :: [SectionId] -> Action ()
atMostOneSection :: [SectionId] -> Action ()
atMostOneSection [SectionId]
xs = do
    Exp Int
selected <- Exp Int -> Action (Exp Int)
mutableInt_ (-Exp Int
1)
    let ensure :: Action ()
ensure = do
            -- find the lowest selected, which isn't already equal to selected
            Exp Int
prev <- Exp Int -> Action (Exp Int)
forall t. Exp t -> Action (Exp t)
constant_ Exp Int
selected
            [(Int, SectionId)] -> ((Int, SectionId) -> Action ()) -> Action ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([(Int, SectionId)] -> [(Int, SectionId)]
forall a. [a] -> [a]
reverse ([(Int, SectionId)] -> [(Int, SectionId)])
-> [(Int, SectionId)] -> [(Int, SectionId)]
forall a b. (a -> b) -> a -> b
$ [Int] -> [SectionId] -> [(Int, SectionId)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] [SectionId]
xs) (((Int, SectionId) -> Action ()) -> Action ())
-> ((Int, SectionId) -> Action ()) -> Action ()
forall a b. (a -> b) -> a -> b
$ \(Int
i,SectionId
x) -> do
                Exp Bool -> Action () -> Action ()
iff_ (Exp Int
prev Exp Int -> Exp Int -> Exp Bool
forall a. Exp a -> Exp a -> Exp Bool
%/= Int -> Exp Int
int Int
i Exp Bool -> Exp Bool -> Exp Bool
%&& SectionId -> SectionFlag -> Exp Bool
sectionGet SectionId
x SectionFlag
SF_Selected) (Action () -> Action ()) -> Action () -> Action ()
forall a b. (a -> b) -> a -> b
$ do
                    Exp Int
selected Exp Int -> Exp Int -> Action ()
forall t. Exp t -> Exp t -> Action ()
@= Int -> Exp Int
int Int
i

            -- ensure only (at most) selected is actually selected
            [(Int, SectionId)] -> ((Int, SectionId) -> Action ()) -> Action ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([Int] -> [SectionId] -> [(Int, SectionId)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] [SectionId]
xs) (((Int, SectionId) -> Action ()) -> Action ())
-> ((Int, SectionId) -> Action ()) -> Action ()
forall a b. (a -> b) -> a -> b
$ \(Int
i,SectionId
x) -> do
                Exp Bool -> Action () -> Action ()
iff_ (Exp Int
selected Exp Int -> Exp Int -> Exp Bool
forall a. Exp a -> Exp a -> Exp Bool
%/= Int -> Exp Int
int Int
i Exp Bool -> Exp Bool -> Exp Bool
%&& SectionId -> SectionFlag -> Exp Bool
sectionGet SectionId
x SectionFlag
SF_Selected) (Action () -> Action ()) -> Action () -> Action ()
forall a b. (a -> b) -> a -> b
$
                    SectionId -> SectionFlag -> Exp Bool -> Action ()
sectionSet SectionId
x SectionFlag
SF_Selected Exp Bool
false
    Action ()
ensure
    Action () -> Action ()
onSelChange Action ()
ensure

exactlyOneSection :: [SectionId] -> Action ()
exactlyOneSection :: [SectionId] -> Action ()
exactlyOneSection [SectionId]
xs = do
    Exp Int
selected <- Exp Int -> Action (Exp Int)
mutableInt_ (-Exp Int
1)

    let ensure :: Action ()
ensure = do
            -- find the lowest selected, which isn't already equal to selected
            Exp Int
prev <- Exp Int -> Action (Exp Int)
forall t. Exp t -> Action (Exp t)
constant_ Exp Int
selected
            [(Int, SectionId)] -> ((Int, SectionId) -> Action ()) -> Action ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([(Int, SectionId)] -> [(Int, SectionId)]
forall a. [a] -> [a]
reverse ([(Int, SectionId)] -> [(Int, SectionId)])
-> [(Int, SectionId)] -> [(Int, SectionId)]
forall a b. (a -> b) -> a -> b
$ [Int] -> [SectionId] -> [(Int, SectionId)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] [SectionId]
xs) (((Int, SectionId) -> Action ()) -> Action ())
-> ((Int, SectionId) -> Action ()) -> Action ()
forall a b. (a -> b) -> a -> b
$ \(Int
i,SectionId
x) ->
                Exp Bool -> Action () -> Action ()
iff_ (Exp Int
prev Exp Int -> Exp Int -> Exp Bool
forall a. Exp a -> Exp a -> Exp Bool
%/= Int -> Exp Int
int Int
i Exp Bool -> Exp Bool -> Exp Bool
%&& SectionId -> SectionFlag -> Exp Bool
sectionGet SectionId
x SectionFlag
SF_Selected) (Action () -> Action ()) -> Action () -> Action ()
forall a b. (a -> b) -> a -> b
$
                    Exp Int
selected Exp Int -> Exp Int -> Action ()
forall t. Exp t -> Exp t -> Action ()
@= Int -> Exp Int
int Int
i
            Exp Bool -> Action () -> Action ()
iff_ (Exp Int
selected Exp Int -> Exp Int -> Exp Bool
forall a. Exp a -> Exp a -> Exp Bool
%== (-Exp Int
1)) (Action () -> Action ()) -> Action () -> Action ()
forall a b. (a -> b) -> a -> b
$
                Exp Int
selected Exp Int -> Exp Int -> Action ()
forall t. Exp t -> Exp t -> Action ()
@= Exp Int
0

            -- ensure only selected is actually selected
            [(Int, SectionId)] -> ((Int, SectionId) -> Action ()) -> Action ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([Int] -> [SectionId] -> [(Int, SectionId)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0..] [SectionId]
xs) (((Int, SectionId) -> Action ()) -> Action ())
-> ((Int, SectionId) -> Action ()) -> Action ()
forall a b. (a -> b) -> a -> b
$ \(Int
i,SectionId
x) -> do
                let b :: Exp Bool
b = Exp Int
selected Exp Int -> Exp Int -> Exp Bool
forall a. Exp a -> Exp a -> Exp Bool
%== Int -> Exp Int
int Int
i
                Exp Bool -> Action () -> Action ()
iff_ (Exp Bool
b Exp Bool -> Exp Bool -> Exp Bool
forall a. Exp a -> Exp a -> Exp Bool
%/= SectionId -> SectionFlag -> Exp Bool
sectionGet SectionId
x SectionFlag
SF_Selected) (Action () -> Action ()) -> Action () -> Action ()
forall a b. (a -> b) -> a -> b
$
                    SectionId -> SectionFlag -> Exp Bool -> Action ()
sectionSet SectionId
x SectionFlag
SF_Selected Exp Bool
b

    Action ()
ensure
    Action () -> Action ()
onSelChange Action ()
ensure