module Util (
    NonEmptyText (..),
    PositiveNumber (..),
    toText,
    toNumber,
    uncheckedAdd,
) where

import Control.Monad

import qualified Data.ByteString.Char8 as BS
import Data.Csv (FromField (..), ToField (..))
import Data.Text (Text)
import Data.Text.Encoding (decodeUtf8Lenient)

import Refined
import Refined.Unsafe

import Numeric.Natural

newtype NonEmptyText = NonEmptyText {runText :: Refined NonEmpty Text}
    deriving (Show, Eq, Ord)

newtype PositiveNumber = PositiveNumber {runNumber :: Refined Positive Natural}
    deriving (Show, Eq, Ord)

instance FromField NonEmptyText where
    parseField s = NonEmptyText <$> (refineFail . decodeUtf8Lenient $ s)

instance FromField PositiveNumber where
    parseField s =
        maybe
            mzero
            ((fmap PositiveNumber . refineFail) . fromIntegral . fst)
            (BS.readInt s)

instance ToField NonEmptyText where
    toField = toField . unrefine . runText

instance ToField PositiveNumber where
    toField = toField . unrefine . runNumber

toText :: NonEmptyText -> Text
toText = unrefine . runText

toNumber :: (Num a) => PositiveNumber -> a
toNumber = fromIntegral . unrefine . runNumber

uncheckedAdd :: PositiveNumber -> PositiveNumber -> PositiveNumber
uncheckedAdd a b = PositiveNumber . unsafeRefine $ toNumber a + toNumber b