module Data.Radius.Attribute.Pair (
  NumberAbstract (..),

  TypedNumber, unsafeTypedNumber, untypeNumber,

  Attribute' (..), Attribute (..), value,

  TypedNumberSet, typed,

  TypedNumberSets (..),
  ) where

import Control.Applicative ((<$>))
import Control.Monad (guard)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Maybe (MaybeT (..))
import Data.ByteString (ByteString)
import Data.Set (Set)
import qualified Data.Set as Set

import Data.Radius.Scalar (AtText, AtString, AtInteger, AtIpV4, )
import qualified Data.Radius.Attribute.Number as Radius


data NumberAbstract a
  = Standard Radius.Number
  | Vendors  a
  deriving (NumberAbstract a -> NumberAbstract a -> Bool
(NumberAbstract a -> NumberAbstract a -> Bool)
-> (NumberAbstract a -> NumberAbstract a -> Bool)
-> Eq (NumberAbstract a)
forall a. Eq a => NumberAbstract a -> NumberAbstract a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => NumberAbstract a -> NumberAbstract a -> Bool
== :: NumberAbstract a -> NumberAbstract a -> Bool
$c/= :: forall a. Eq a => NumberAbstract a -> NumberAbstract a -> Bool
/= :: NumberAbstract a -> NumberAbstract a -> Bool
Eq, Eq (NumberAbstract a)
Eq (NumberAbstract a) =>
(NumberAbstract a -> NumberAbstract a -> Ordering)
-> (NumberAbstract a -> NumberAbstract a -> Bool)
-> (NumberAbstract a -> NumberAbstract a -> Bool)
-> (NumberAbstract a -> NumberAbstract a -> Bool)
-> (NumberAbstract a -> NumberAbstract a -> Bool)
-> (NumberAbstract a -> NumberAbstract a -> NumberAbstract a)
-> (NumberAbstract a -> NumberAbstract a -> NumberAbstract a)
-> Ord (NumberAbstract a)
NumberAbstract a -> NumberAbstract a -> Bool
NumberAbstract a -> NumberAbstract a -> Ordering
NumberAbstract a -> NumberAbstract a -> NumberAbstract a
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
forall a. Ord a => Eq (NumberAbstract a)
forall a. Ord a => NumberAbstract a -> NumberAbstract a -> Bool
forall a. Ord a => NumberAbstract a -> NumberAbstract a -> Ordering
forall a.
Ord a =>
NumberAbstract a -> NumberAbstract a -> NumberAbstract a
$ccompare :: forall a. Ord a => NumberAbstract a -> NumberAbstract a -> Ordering
compare :: NumberAbstract a -> NumberAbstract a -> Ordering
$c< :: forall a. Ord a => NumberAbstract a -> NumberAbstract a -> Bool
< :: NumberAbstract a -> NumberAbstract a -> Bool
$c<= :: forall a. Ord a => NumberAbstract a -> NumberAbstract a -> Bool
<= :: NumberAbstract a -> NumberAbstract a -> Bool
$c> :: forall a. Ord a => NumberAbstract a -> NumberAbstract a -> Bool
> :: NumberAbstract a -> NumberAbstract a -> Bool
$c>= :: forall a. Ord a => NumberAbstract a -> NumberAbstract a -> Bool
>= :: NumberAbstract a -> NumberAbstract a -> Bool
$cmax :: forall a.
Ord a =>
NumberAbstract a -> NumberAbstract a -> NumberAbstract a
max :: NumberAbstract a -> NumberAbstract a -> NumberAbstract a
$cmin :: forall a.
Ord a =>
NumberAbstract a -> NumberAbstract a -> NumberAbstract a
min :: NumberAbstract a -> NumberAbstract a -> NumberAbstract a
Ord, Int -> NumberAbstract a -> ShowS
[NumberAbstract a] -> ShowS
NumberAbstract a -> String
(Int -> NumberAbstract a -> ShowS)
-> (NumberAbstract a -> String)
-> ([NumberAbstract a] -> ShowS)
-> Show (NumberAbstract a)
forall a. Show a => Int -> NumberAbstract a -> ShowS
forall a. Show a => [NumberAbstract a] -> ShowS
forall a. Show a => NumberAbstract a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> NumberAbstract a -> ShowS
showsPrec :: Int -> NumberAbstract a -> ShowS
$cshow :: forall a. Show a => NumberAbstract a -> String
show :: NumberAbstract a -> String
$cshowList :: forall a. Show a => [NumberAbstract a] -> ShowS
showList :: [NumberAbstract a] -> ShowS
Show)


newtype TypedNumber v a =
  TypedNumber (NumberAbstract v)
  deriving (TypedNumber v a -> TypedNumber v a -> Bool
(TypedNumber v a -> TypedNumber v a -> Bool)
-> (TypedNumber v a -> TypedNumber v a -> Bool)
-> Eq (TypedNumber v a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall v a. Eq v => TypedNumber v a -> TypedNumber v a -> Bool
$c== :: forall v a. Eq v => TypedNumber v a -> TypedNumber v a -> Bool
== :: TypedNumber v a -> TypedNumber v a -> Bool
$c/= :: forall v a. Eq v => TypedNumber v a -> TypedNumber v a -> Bool
/= :: TypedNumber v a -> TypedNumber v a -> Bool
Eq, Eq (TypedNumber v a)
Eq (TypedNumber v a) =>
(TypedNumber v a -> TypedNumber v a -> Ordering)
-> (TypedNumber v a -> TypedNumber v a -> Bool)
-> (TypedNumber v a -> TypedNumber v a -> Bool)
-> (TypedNumber v a -> TypedNumber v a -> Bool)
-> (TypedNumber v a -> TypedNumber v a -> Bool)
-> (TypedNumber v a -> TypedNumber v a -> TypedNumber v a)
-> (TypedNumber v a -> TypedNumber v a -> TypedNumber v a)
-> Ord (TypedNumber v a)
TypedNumber v a -> TypedNumber v a -> Bool
TypedNumber v a -> TypedNumber v a -> Ordering
TypedNumber v a -> TypedNumber v a -> TypedNumber v a
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
forall v a. Ord v => Eq (TypedNumber v a)
forall v a. Ord v => TypedNumber v a -> TypedNumber v a -> Bool
forall v a. Ord v => TypedNumber v a -> TypedNumber v a -> Ordering
forall v a.
Ord v =>
TypedNumber v a -> TypedNumber v a -> TypedNumber v a
$ccompare :: forall v a. Ord v => TypedNumber v a -> TypedNumber v a -> Ordering
compare :: TypedNumber v a -> TypedNumber v a -> Ordering
$c< :: forall v a. Ord v => TypedNumber v a -> TypedNumber v a -> Bool
< :: TypedNumber v a -> TypedNumber v a -> Bool
$c<= :: forall v a. Ord v => TypedNumber v a -> TypedNumber v a -> Bool
<= :: TypedNumber v a -> TypedNumber v a -> Bool
$c> :: forall v a. Ord v => TypedNumber v a -> TypedNumber v a -> Bool
> :: TypedNumber v a -> TypedNumber v a -> Bool
$c>= :: forall v a. Ord v => TypedNumber v a -> TypedNumber v a -> Bool
>= :: TypedNumber v a -> TypedNumber v a -> Bool
$cmax :: forall v a.
Ord v =>
TypedNumber v a -> TypedNumber v a -> TypedNumber v a
max :: TypedNumber v a -> TypedNumber v a -> TypedNumber v a
$cmin :: forall v a.
Ord v =>
TypedNumber v a -> TypedNumber v a -> TypedNumber v a
min :: TypedNumber v a -> TypedNumber v a -> TypedNumber v a
Ord, Int -> TypedNumber v a -> ShowS
[TypedNumber v a] -> ShowS
TypedNumber v a -> String
(Int -> TypedNumber v a -> ShowS)
-> (TypedNumber v a -> String)
-> ([TypedNumber v a] -> ShowS)
-> Show (TypedNumber v a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall v a. Show v => Int -> TypedNumber v a -> ShowS
forall v a. Show v => [TypedNumber v a] -> ShowS
forall v a. Show v => TypedNumber v a -> String
$cshowsPrec :: forall v a. Show v => Int -> TypedNumber v a -> ShowS
showsPrec :: Int -> TypedNumber v a -> ShowS
$cshow :: forall v a. Show v => TypedNumber v a -> String
show :: TypedNumber v a -> String
$cshowList :: forall v a. Show v => [TypedNumber v a] -> ShowS
showList :: [TypedNumber v a] -> ShowS
Show)

unsafeTypedNumber :: NumberAbstract v -> TypedNumber v a
unsafeTypedNumber :: forall v a. NumberAbstract v -> TypedNumber v a
unsafeTypedNumber = NumberAbstract v -> TypedNumber v a
forall v a. NumberAbstract v -> TypedNumber v a
TypedNumber

untypeNumber :: TypedNumber v a -> NumberAbstract v
untypeNumber :: forall v a. TypedNumber v a -> NumberAbstract v
untypeNumber (TypedNumber NumberAbstract v
n) = NumberAbstract v
n

data Attribute' v =
  Attribute' !(NumberAbstract v) !ByteString
  deriving (Attribute' v -> Attribute' v -> Bool
(Attribute' v -> Attribute' v -> Bool)
-> (Attribute' v -> Attribute' v -> Bool) -> Eq (Attribute' v)
forall v. Eq v => Attribute' v -> Attribute' v -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall v. Eq v => Attribute' v -> Attribute' v -> Bool
== :: Attribute' v -> Attribute' v -> Bool
$c/= :: forall v. Eq v => Attribute' v -> Attribute' v -> Bool
/= :: Attribute' v -> Attribute' v -> Bool
Eq, Eq (Attribute' v)
Eq (Attribute' v) =>
(Attribute' v -> Attribute' v -> Ordering)
-> (Attribute' v -> Attribute' v -> Bool)
-> (Attribute' v -> Attribute' v -> Bool)
-> (Attribute' v -> Attribute' v -> Bool)
-> (Attribute' v -> Attribute' v -> Bool)
-> (Attribute' v -> Attribute' v -> Attribute' v)
-> (Attribute' v -> Attribute' v -> Attribute' v)
-> Ord (Attribute' v)
Attribute' v -> Attribute' v -> Bool
Attribute' v -> Attribute' v -> Ordering
Attribute' v -> Attribute' v -> Attribute' v
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
forall v. Ord v => Eq (Attribute' v)
forall v. Ord v => Attribute' v -> Attribute' v -> Bool
forall v. Ord v => Attribute' v -> Attribute' v -> Ordering
forall v. Ord v => Attribute' v -> Attribute' v -> Attribute' v
$ccompare :: forall v. Ord v => Attribute' v -> Attribute' v -> Ordering
compare :: Attribute' v -> Attribute' v -> Ordering
$c< :: forall v. Ord v => Attribute' v -> Attribute' v -> Bool
< :: Attribute' v -> Attribute' v -> Bool
$c<= :: forall v. Ord v => Attribute' v -> Attribute' v -> Bool
<= :: Attribute' v -> Attribute' v -> Bool
$c> :: forall v. Ord v => Attribute' v -> Attribute' v -> Bool
> :: Attribute' v -> Attribute' v -> Bool
$c>= :: forall v. Ord v => Attribute' v -> Attribute' v -> Bool
>= :: Attribute' v -> Attribute' v -> Bool
$cmax :: forall v. Ord v => Attribute' v -> Attribute' v -> Attribute' v
max :: Attribute' v -> Attribute' v -> Attribute' v
$cmin :: forall v. Ord v => Attribute' v -> Attribute' v -> Attribute' v
min :: Attribute' v -> Attribute' v -> Attribute' v
Ord, Int -> Attribute' v -> ShowS
[Attribute' v] -> ShowS
Attribute' v -> String
(Int -> Attribute' v -> ShowS)
-> (Attribute' v -> String)
-> ([Attribute' v] -> ShowS)
-> Show (Attribute' v)
forall v. Show v => Int -> Attribute' v -> ShowS
forall v. Show v => [Attribute' v] -> ShowS
forall v. Show v => Attribute' v -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall v. Show v => Int -> Attribute' v -> ShowS
showsPrec :: Int -> Attribute' v -> ShowS
$cshow :: forall v. Show v => Attribute' v -> String
show :: Attribute' v -> String
$cshowList :: forall v. Show v => [Attribute' v] -> ShowS
showList :: [Attribute' v] -> ShowS
Show)

data Attribute v a =
  Attribute !(TypedNumber v a) !a
  deriving (Attribute v a -> Attribute v a -> Bool
(Attribute v a -> Attribute v a -> Bool)
-> (Attribute v a -> Attribute v a -> Bool) -> Eq (Attribute v a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall v a. (Eq v, Eq a) => Attribute v a -> Attribute v a -> Bool
$c== :: forall v a. (Eq v, Eq a) => Attribute v a -> Attribute v a -> Bool
== :: Attribute v a -> Attribute v a -> Bool
$c/= :: forall v a. (Eq v, Eq a) => Attribute v a -> Attribute v a -> Bool
/= :: Attribute v a -> Attribute v a -> Bool
Eq, Eq (Attribute v a)
Eq (Attribute v a) =>
(Attribute v a -> Attribute v a -> Ordering)
-> (Attribute v a -> Attribute v a -> Bool)
-> (Attribute v a -> Attribute v a -> Bool)
-> (Attribute v a -> Attribute v a -> Bool)
-> (Attribute v a -> Attribute v a -> Bool)
-> (Attribute v a -> Attribute v a -> Attribute v a)
-> (Attribute v a -> Attribute v a -> Attribute v a)
-> Ord (Attribute v a)
Attribute v a -> Attribute v a -> Bool
Attribute v a -> Attribute v a -> Ordering
Attribute v a -> Attribute v a -> Attribute v a
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
forall v a. (Ord v, Ord a) => Eq (Attribute v a)
forall v a.
(Ord v, Ord a) =>
Attribute v a -> Attribute v a -> Bool
forall v a.
(Ord v, Ord a) =>
Attribute v a -> Attribute v a -> Ordering
forall v a.
(Ord v, Ord a) =>
Attribute v a -> Attribute v a -> Attribute v a
$ccompare :: forall v a.
(Ord v, Ord a) =>
Attribute v a -> Attribute v a -> Ordering
compare :: Attribute v a -> Attribute v a -> Ordering
$c< :: forall v a.
(Ord v, Ord a) =>
Attribute v a -> Attribute v a -> Bool
< :: Attribute v a -> Attribute v a -> Bool
$c<= :: forall v a.
(Ord v, Ord a) =>
Attribute v a -> Attribute v a -> Bool
<= :: Attribute v a -> Attribute v a -> Bool
$c> :: forall v a.
(Ord v, Ord a) =>
Attribute v a -> Attribute v a -> Bool
> :: Attribute v a -> Attribute v a -> Bool
$c>= :: forall v a.
(Ord v, Ord a) =>
Attribute v a -> Attribute v a -> Bool
>= :: Attribute v a -> Attribute v a -> Bool
$cmax :: forall v a.
(Ord v, Ord a) =>
Attribute v a -> Attribute v a -> Attribute v a
max :: Attribute v a -> Attribute v a -> Attribute v a
$cmin :: forall v a.
(Ord v, Ord a) =>
Attribute v a -> Attribute v a -> Attribute v a
min :: Attribute v a -> Attribute v a -> Attribute v a
Ord, Int -> Attribute v a -> ShowS
[Attribute v a] -> ShowS
Attribute v a -> String
(Int -> Attribute v a -> ShowS)
-> (Attribute v a -> String)
-> ([Attribute v a] -> ShowS)
-> Show (Attribute v a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall v a. (Show v, Show a) => Int -> Attribute v a -> ShowS
forall v a. (Show v, Show a) => [Attribute v a] -> ShowS
forall v a. (Show v, Show a) => Attribute v a -> String
$cshowsPrec :: forall v a. (Show v, Show a) => Int -> Attribute v a -> ShowS
showsPrec :: Int -> Attribute v a -> ShowS
$cshow :: forall v a. (Show v, Show a) => Attribute v a -> String
show :: Attribute v a -> String
$cshowList :: forall v a. (Show v, Show a) => [Attribute v a] -> ShowS
showList :: [Attribute v a] -> ShowS
Show)

value :: Attribute v a -> a
value :: forall v a. Attribute v a -> a
value (Attribute TypedNumber v a
_ a
v) = a
v


type TypedNumberSet v a = Set (TypedNumber v a)

{-
-- | Retryable error context with anthor attirbute value type /t/ /m/, and parse error context /m/.
typed :: (Monad m, Functor m, MonadTrans t, MonadPlus (t m))
      => TypedNumberSet vt
      -> (ByteString -> m a)
      -> Attribute'
      -> t m (Attribute a)
 -}
-- | Retryable error context with anthor attirbute value type 'MaybeT' /m/, and parse error context /m/.
typed :: (Monad m, Functor m, Ord v)
      => TypedNumberSet v a
      -> (ByteString -> m b)
      -> Attribute' v
      -> MaybeT m (Attribute v b)
typed :: forall (m :: * -> *) v a b.
(Monad m, Functor m, Ord v) =>
TypedNumberSet v a
-> (ByteString -> m b) -> Attribute' v -> MaybeT m (Attribute v b)
typed TypedNumberSet v a
s ByteString -> m b
parse (Attribute' NumberAbstract v
n ByteString
d) = do
  let typedAN :: TypedNumber v a
typedAN = NumberAbstract v -> TypedNumber v a
forall v a. NumberAbstract v -> TypedNumber v a
unsafeTypedNumber NumberAbstract v
n
  Bool -> MaybeT m ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> MaybeT m ()) -> Bool -> MaybeT m ()
forall a b. (a -> b) -> a -> b
$ TypedNumber v a
forall {a}. TypedNumber v a
typedAN TypedNumber v a -> TypedNumberSet v a -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` TypedNumberSet v a
s
  m (Attribute v b) -> MaybeT m (Attribute v b)
forall (m :: * -> *) a. Monad m => m a -> MaybeT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Attribute v b) -> MaybeT m (Attribute v b))
-> m (Attribute v b) -> MaybeT m (Attribute v b)
forall a b. (a -> b) -> a -> b
$ TypedNumber v b -> b -> Attribute v b
forall v a. TypedNumber v a -> a -> Attribute v a
Attribute TypedNumber v b
forall {a}. TypedNumber v a
typedAN (b -> Attribute v b) -> m b -> m (Attribute v b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteString -> m b
parse ByteString
d


class TypedNumberSets v where
  attributeNumbersText    :: TypedNumberSet v AtText
  attributeNumbersString  :: TypedNumberSet v AtString
  attributeNumbersInteger :: TypedNumberSet v AtInteger
  attributeNumbersIpV4    :: TypedNumberSet v AtIpV4