{-| Basic padding and "justification" of lists.  -}
module Padding
    ( leftPad
    , rightPad
    , rightPadNoSquash
    , midPad
    , midPadL
    , rotU
    , rotD
    , rotListAt
    , insertAt
    )
    where
leftPad :: Int -> a -> [a] -> [a]
{-# INLINE leftPad #-}
leftPad i x xs = reverse $ take i $ reverse (take i xs) ++ repeat x

rightPad :: Int -> a -> [a] -> [a]
{-# INLINE rightPad #-}
rightPad i x xs = take i $ xs ++ repeat x

rightPadNoSquash :: Int -> a -> [a] -> [a]
{-# INLINE rightPadNoSquash #-}
rightPadNoSquash i x xs = take (max i $ length xs) $ xs ++ repeat x

midPad :: Int -> a -> [a] -> [a] -> [a]
{-# INLINE midPad #-}
midPad i x xs ys = xs ++ replicate j x ++ ys
  where 
    j = i - (length xs + length ys)

midPadL :: Int -> a -> [a] -> [a] -> [a]
{-# INLINE midPadL #-}
midPadL i x xs ys = take j (xs ++ repeat x) ++ ys
  where 
    j = i - length ys

rotU :: [a] -> [a]
{-# INLINE rotU #-}
rotU [] = []
rotU (x:xs) = xs ++ [x]

rotD :: [a] -> [a]
{-# INLINE rotD #-}
rotD [] = []
rotD xs = last xs : init xs

rotListAt :: Eq a => a -> [a] -> [a]
rotListAt x' xs = f x' xs []
  where
    f x (y:ys) zs
        | y == x    = y:ys ++ zs
        | otherwise = f x ys (y:zs)
    f _ [] zs = zs

insertAt :: Int -> a -> [a] -> [a]
insertAt i x xs = let (ys,zs) = splitAt i xs in ys ++ [x] ++ zs

--listElementOthersPairs :: [a] -> [(a,[a])]
--listElementOthersPairs (x:xs) = go [] x xs
--  where
--    go ys y [] = [(y,ys)]
--    go ys y (z:zs) = (y,ys++zs): go (y:ys) z zs
