module Termbox.Internal.Pos
  ( Pos (..),
    posUp,
    posDown,
    posLeft,
    posRight,
  )
where

import GHC.Generics (Generic)

-- | A relative terminal position.
data Pos = Pos
  { Pos -> Int
row :: {-# UNPACK #-} !Int,
    Pos -> Int
col :: {-# UNPACK #-} !Int
  }
  deriving stock (Pos -> Pos -> Bool
(Pos -> Pos -> Bool) -> (Pos -> Pos -> Bool) -> Eq Pos
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Pos -> Pos -> Bool
== :: Pos -> Pos -> Bool
$c/= :: Pos -> Pos -> Bool
/= :: Pos -> Pos -> Bool
Eq, (forall x. Pos -> Rep Pos x)
-> (forall x. Rep Pos x -> Pos) -> Generic Pos
forall x. Rep Pos x -> Pos
forall x. Pos -> Rep Pos x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Pos -> Rep Pos x
from :: forall x. Pos -> Rep Pos x
$cto :: forall x. Rep Pos x -> Pos
to :: forall x. Rep Pos x -> Pos
Generic, Eq Pos
Eq Pos =>
(Pos -> Pos -> Ordering)
-> (Pos -> Pos -> Bool)
-> (Pos -> Pos -> Bool)
-> (Pos -> Pos -> Bool)
-> (Pos -> Pos -> Bool)
-> (Pos -> Pos -> Pos)
-> (Pos -> Pos -> Pos)
-> Ord Pos
Pos -> Pos -> Bool
Pos -> Pos -> Ordering
Pos -> Pos -> Pos
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Pos -> Pos -> Ordering
compare :: Pos -> Pos -> Ordering
$c< :: Pos -> Pos -> Bool
< :: Pos -> Pos -> Bool
$c<= :: Pos -> Pos -> Bool
<= :: Pos -> Pos -> Bool
$c> :: Pos -> Pos -> Bool
> :: Pos -> Pos -> Bool
$c>= :: Pos -> Pos -> Bool
>= :: Pos -> Pos -> Bool
$cmax :: Pos -> Pos -> Pos
max :: Pos -> Pos -> Pos
$cmin :: Pos -> Pos -> Pos
min :: Pos -> Pos -> Pos
Ord, Int -> Pos -> ShowS
[Pos] -> ShowS
Pos -> String
(Int -> Pos -> ShowS)
-> (Pos -> String) -> ([Pos] -> ShowS) -> Show Pos
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Pos -> ShowS
showsPrec :: Int -> Pos -> ShowS
$cshow :: Pos -> String
show :: Pos -> String
$cshowList :: [Pos] -> ShowS
showList :: [Pos] -> ShowS
Show)

instance Monoid Pos where
  mempty :: Pos
mempty = Int -> Int -> Pos
Pos Int
0 Int
0

instance Semigroup Pos where
  Pos Int
row1 Int
col1 <> :: Pos -> Pos -> Pos
<> Pos Int
row2 Int
col2 =
    Int -> Int -> Pos
Pos (Int
row1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
row2) (Int
col1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
col2)

-- | Move a position up.
posUp :: Int -> Pos -> Pos
posUp :: Int -> Pos -> Pos
posUp Int
n (Pos Int
row Int
col) =
  Int -> Int -> Pos
Pos (Int
row Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n) Int
col

-- | Move a position down.
posDown :: Int -> Pos -> Pos
posDown :: Int -> Pos -> Pos
posDown Int
n (Pos Int
row Int
col) =
  Int -> Int -> Pos
Pos (Int
row Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n) Int
col

-- | Move a position left.
posLeft :: Int -> Pos -> Pos
posLeft :: Int -> Pos -> Pos
posLeft Int
n (Pos Int
row Int
col) =
  Int -> Int -> Pos
Pos Int
row (Int
col Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n)

-- | Move a position right.
posRight :: Int -> Pos -> Pos
posRight :: Int -> Pos -> Pos
posRight Int
n (Pos Int
row Int
col) =
  Int -> Int -> Pos
Pos Int
row (Int
col Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n)