module System.Console.ListPrompt.Internal
  where

import           Control.Applicative             ((<$>))
import           Control.Exception               (bracket_)
import           Data.Default                    (def)
import           System.Console.ANSI
import           System.Console.Terminal.Size    (Window (..), size)
import           System.IO                       (BufferMode, Handle,
                                                  hGetBuffering, hSetBuffering,
                                                  hSetEcho, stdin)

import           System.Console.ListPrompt.Types

-- |
-- Calculates the optimal position for the prompt optionally with the
-- terminal's size and the number of available choices
getDimensions :: Int -> Maybe (Window Int) -> ListPromptDimensions
getDimensions numChoices (Just (Window h w)) =
    ListPromptDimensions { targetCoordinate = tc
                         , listPromptSize = lps
                         }
  where
    margin = 3
    padding = 3
    tc = ((h `div` 2 - numChoices `div` 2) - padding, padding)
    lps = (numChoices + margin, w - margin * 2)
getDimensions _ Nothing = def

getDimensionsIO :: Int -> IO ListPromptDimensions
getDimensionsIO n = getDimensions n <$> size

withNoCursor :: IO a -> IO a
withNoCursor = bracket_ hideCursor showCursor

withNoEcho :: IO a -> IO a
withNoEcho = bracket_ (hSetEcho stdin False) (hSetEcho stdin True)

withNoBuffering :: Handle -> BufferMode -> IO a -> IO a
withNoBuffering handle newBuffering action = do
    originalBuffering <- hGetBuffering handle
    bracket_
        (hSetBuffering handle newBuffering)
        (hSetBuffering handle originalBuffering)
        action