    {-# LANGUAGE DeriveGeneric #-}
    -- | Ring buffers.
    module Game.LambdaHack.Common.RingBuffer
      ( RingBuffer
      , empty, cons, toList, length
      ) where

    import Prelude ()

    import Game.LambdaHack.Core.Prelude hiding (length, uncons)

    import           Data.Binary
    import qualified Data.Foldable as Foldable
    import qualified Data.Sequence as Seq
    import           GHC.Generics (Generic)

    -- | Ring buffers of a size determined at initialization.
    data RingBuffer a = RingBuffer
      { forall a. RingBuffer a -> Seq a
    rbCarrier :: Seq.Seq a
      , forall a. RingBuffer a -> Int
    rbMaxSize :: Int
      , forall a. RingBuffer a -> Int
    rbNext    :: Int
      , forall a. RingBuffer a -> Int
    rbLength  :: Int
      }
      deriving (Int -> RingBuffer a -> ShowS
    [RingBuffer a] -> ShowS
    RingBuffer a -> String
    (Int -> RingBuffer a -> ShowS)
    -> (RingBuffer a -> String)
    -> ([RingBuffer a] -> ShowS)
    -> Show (RingBuffer a)
    forall a. Show a => Int -> RingBuffer a -> ShowS
    forall a. Show a => [RingBuffer a] -> ShowS
    forall a. Show a => RingBuffer a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall a. Show a => Int -> RingBuffer a -> ShowS
    showsPrec :: Int -> RingBuffer a -> ShowS
    $cshow :: forall a. Show a => RingBuffer a -> String
    show :: RingBuffer a -> String
    $cshowList :: forall a. Show a => [RingBuffer a] -> ShowS
    showList :: [RingBuffer a] -> ShowS
    Show, (forall x. RingBuffer a -> Rep (RingBuffer a) x)
    -> (forall x. Rep (RingBuffer a) x -> RingBuffer a)
    -> Generic (RingBuffer a)
    forall x. Rep (RingBuffer a) x -> RingBuffer a
    forall x. RingBuffer a -> Rep (RingBuffer a) x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    forall a x. Rep (RingBuffer a) x -> RingBuffer a
    forall a x. RingBuffer a -> Rep (RingBuffer a) x
    $cfrom :: forall a x. RingBuffer a -> Rep (RingBuffer a) x
    from :: forall x. RingBuffer a -> Rep (RingBuffer a) x
    $cto :: forall a x. Rep (RingBuffer a) x -> RingBuffer a
    to :: forall x. Rep (RingBuffer a) x -> RingBuffer a
    Generic)

    instance Binary a => Binary (RingBuffer a)

    -- Only takes O(log n)).
    empty :: Int -> a -> RingBuffer a
    empty :: forall a. Int -> a -> RingBuffer a
    empty Int
    size a
    dummy =
      let rbMaxSize :: Int
    rbMaxSize = Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    max Int
    1 Int
    size
      in Seq a -> Int -> Int -> Int -> RingBuffer a
    forall a. Seq a -> Int -> Int -> Int -> RingBuffer a
    RingBuffer (Int -> a -> Seq a
    forall a. Int -> a -> Seq a
    Seq.replicate Int
    rbMaxSize a
    dummy) Int
    rbMaxSize Int
    0 Int
    0

    cons :: a -> RingBuffer a -> RingBuffer a
    cons :: forall a. a -> RingBuffer a -> RingBuffer a
    cons a
    a RingBuffer{Int
    Seq a
    rbCarrier :: forall a. RingBuffer a -> Seq a
    rbMaxSize :: forall a. RingBuffer a -> Int
    rbNext :: forall a. RingBuffer a -> Int
    rbLength :: forall a. RingBuffer a -> Int
    rbCarrier :: Seq a
    rbMaxSize :: Int
    rbNext :: Int
    rbLength :: Int
    ..} =
      let incNext :: Int
    incNext = (Int
    rbNext Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1) Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `mod` Int
    rbMaxSize
          incLength :: Int
    incLength = Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    min Int
    rbMaxSize (Int -> Int) -> Int -> Int
    forall a b. (a -> b) -> a -> b
    $ Int
    rbLength Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1
      in Seq a -> Int -> Int -> Int -> RingBuffer a
    forall a. Seq a -> Int -> Int -> Int -> RingBuffer a
    RingBuffer (Int -> a -> Seq a -> Seq a
    forall a. Int -> a -> Seq a -> Seq a
    Seq.update Int
    rbNext a
    a Seq a
    rbCarrier) Int
    rbMaxSize Int
    incNext Int
    incLength

    toList :: RingBuffer a -> [a]
    toList :: forall a. RingBuffer a -> [a]
    toList RingBuffer{Int
    Seq a
    rbCarrier :: forall a. RingBuffer a -> Seq a
    rbMaxSize :: forall a. RingBuffer a -> Int
    rbNext :: forall a. RingBuffer a -> Int
    rbLength :: forall a. RingBuffer a -> Int
    rbCarrier :: Seq a
    rbMaxSize :: Int
    rbNext :: Int
    rbLength :: Int
    ..} =
      let l :: [a]
    l = Seq a -> [a]
    forall a. Seq a -> [a]
    forall (t :: * -> *) a. Foldable t => t a -> [a]
    Foldable.toList Seq a
    rbCarrier
          start :: Int
    start = (Int
    rbNext Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    rbMaxSize Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    rbLength) Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `mod` Int
    rbMaxSize
      in Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    take Int
    rbLength ([a] -> [a]) -> [a] -> [a]
    forall a b. (a -> b) -> a -> b
    $ Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    drop Int
    start ([a] -> [a]) -> [a] -> [a]
    forall a b. (a -> b) -> a -> b
    $ [a]
    l [a] -> [a] -> [a]
    forall a. [a] -> [a] -> [a]
    ++ [a]
    l

    length :: RingBuffer a -> Int
    length :: forall a. RingBuffer a -> Int
    length RingBuffer{Int
    rbLength :: forall a. RingBuffer a -> Int
    rbLength :: Int
    rbLength} = Int
    rbLength