module HaskellWorks.Data.BalancedParens.Internal.Slow.FindCloseN.Generic
  ( findCloseN
  ) where

import HaskellWorks.Data.BalancedParens.CloseAt
import HaskellWorks.Data.Bits.BitLength
import HaskellWorks.Data.Bits.BitWise
import HaskellWorks.Data.Positioning

-- | Find the position of the corresponding close parenthesis carrying in a number of open parentheses starting from a given position.
--
-- All positions are one based.
--
-- This is a reference implementation.
--
-- >>> :set -XTypeApplications
-- >>> import HaskellWorks.Data.Bits.BitRead
-- >>> import Data.Maybe
-- >>> import Data.Word
-- >>> findCloseN (fromJust (bitRead @Word64 "1100000")) 0 1
-- Just 4
-- >>> findCloseN (fromJust (bitRead @Word64 "1100000")) 0 2
-- Just 3
-- >>> findCloseN (fromJust (bitRead @Word64 "1100000")) 1 1
-- Just 5
-- >>> findCloseN (fromJust (bitRead @Word64 "1100000")) 1 2
-- Just 4
findCloseN :: (BitLength a, CloseAt a, TestBit a) => a -> Count -> Count -> Maybe Count
findCloseN :: a -> Count -> Count -> Maybe Count
findCloseN a
v Count
c Count
p = if Count
0 Count -> Count -> Bool
forall a. Ord a => a -> a -> Bool
< Count
p
  then if a
v a -> Count -> Bool
forall v. CloseAt v => v -> Count -> Bool
`closeAt` Count
p
    then if Count
c Count -> Count -> Bool
forall a. Ord a => a -> a -> Bool
<= Count
1
      then Count -> Maybe Count
forall a. a -> Maybe a
Just Count
p
      else a -> Count -> Count -> Maybe Count
forall a.
(BitLength a, CloseAt a, TestBit a) =>
a -> Count -> Count -> Maybe Count
findCloseN a
v (Count
c Count -> Count -> Count
forall a. Num a => a -> a -> a
- Count
1) (Count
p Count -> Count -> Count
forall a. Num a => a -> a -> a
+ Count
1)
    else a -> Count -> Count -> Maybe Count
forall a.
(BitLength a, CloseAt a, TestBit a) =>
a -> Count -> Count -> Maybe Count
findCloseN a
v (Count
c Count -> Count -> Count
forall a. Num a => a -> a -> a
+ Count
1) (Count
p Count -> Count -> Count
forall a. Num a => a -> a -> a
+ Count
1)
  else Maybe Count
forall a. Maybe a
Nothing
{-# INLINE findCloseN #-}