{-# LANGUAGE ScopedTypeVariables #-}

module Blucontrol.Value.RGB (
  RGB (..)
) where

import Control.DeepSeq
import Data.Default
import Data.Word
import GHC.Generics

-- | Values for the colors 'red', 'green' and 'blue'
data RGB a = RGB { RGB a -> a
red :: a
                 , RGB a -> a
green :: a
                 , RGB a -> a
blue :: a
                 }
  deriving (RGB a
RGB a -> RGB a -> Bounded (RGB a)
forall a. a -> a -> Bounded a
forall a. Bounded a => RGB a
maxBound :: RGB a
$cmaxBound :: forall a. Bounded a => RGB a
minBound :: RGB a
$cminBound :: forall a. Bounded a => RGB a
Bounded, RGB a -> RGB a -> Bool
(RGB a -> RGB a -> Bool) -> (RGB a -> RGB a -> Bool) -> Eq (RGB a)
forall a. Eq a => RGB a -> RGB a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RGB a -> RGB a -> Bool
$c/= :: forall a. Eq a => RGB a -> RGB a -> Bool
== :: RGB a -> RGB a -> Bool
$c== :: forall a. Eq a => RGB a -> RGB a -> Bool
Eq, (forall x. RGB a -> Rep (RGB a) x)
-> (forall x. Rep (RGB a) x -> RGB a) -> Generic (RGB a)
forall x. Rep (RGB a) x -> RGB a
forall x. RGB a -> Rep (RGB a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (RGB a) x -> RGB a
forall a x. RGB a -> Rep (RGB a) x
$cto :: forall a x. Rep (RGB a) x -> RGB a
$cfrom :: forall a x. RGB a -> Rep (RGB a) x
Generic, Eq (RGB a)
Eq (RGB a)
-> (RGB a -> RGB a -> Ordering)
-> (RGB a -> RGB a -> Bool)
-> (RGB a -> RGB a -> Bool)
-> (RGB a -> RGB a -> Bool)
-> (RGB a -> RGB a -> Bool)
-> (RGB a -> RGB a -> RGB a)
-> (RGB a -> RGB a -> RGB a)
-> Ord (RGB a)
RGB a -> RGB a -> Bool
RGB a -> RGB a -> Ordering
RGB a -> RGB a -> RGB 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 (RGB a)
forall a. Ord a => RGB a -> RGB a -> Bool
forall a. Ord a => RGB a -> RGB a -> Ordering
forall a. Ord a => RGB a -> RGB a -> RGB a
min :: RGB a -> RGB a -> RGB a
$cmin :: forall a. Ord a => RGB a -> RGB a -> RGB a
max :: RGB a -> RGB a -> RGB a
$cmax :: forall a. Ord a => RGB a -> RGB a -> RGB a
>= :: RGB a -> RGB a -> Bool
$c>= :: forall a. Ord a => RGB a -> RGB a -> Bool
> :: RGB a -> RGB a -> Bool
$c> :: forall a. Ord a => RGB a -> RGB a -> Bool
<= :: RGB a -> RGB a -> Bool
$c<= :: forall a. Ord a => RGB a -> RGB a -> Bool
< :: RGB a -> RGB a -> Bool
$c< :: forall a. Ord a => RGB a -> RGB a -> Bool
compare :: RGB a -> RGB a -> Ordering
$ccompare :: forall a. Ord a => RGB a -> RGB a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (RGB a)
Ord, ReadPrec [RGB a]
ReadPrec (RGB a)
Int -> ReadS (RGB a)
ReadS [RGB a]
(Int -> ReadS (RGB a))
-> ReadS [RGB a]
-> ReadPrec (RGB a)
-> ReadPrec [RGB a]
-> Read (RGB a)
forall a. Read a => ReadPrec [RGB a]
forall a. Read a => ReadPrec (RGB a)
forall a. Read a => Int -> ReadS (RGB a)
forall a. Read a => ReadS [RGB a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [RGB a]
$creadListPrec :: forall a. Read a => ReadPrec [RGB a]
readPrec :: ReadPrec (RGB a)
$creadPrec :: forall a. Read a => ReadPrec (RGB a)
readList :: ReadS [RGB a]
$creadList :: forall a. Read a => ReadS [RGB a]
readsPrec :: Int -> ReadS (RGB a)
$creadsPrec :: forall a. Read a => Int -> ReadS (RGB a)
Read, Int -> RGB a -> ShowS
[RGB a] -> ShowS
RGB a -> String
(Int -> RGB a -> ShowS)
-> (RGB a -> String) -> ([RGB a] -> ShowS) -> Show (RGB a)
forall a. Show a => Int -> RGB a -> ShowS
forall a. Show a => [RGB a] -> ShowS
forall a. Show a => RGB a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RGB a] -> ShowS
$cshowList :: forall a. Show a => [RGB a] -> ShowS
show :: RGB a -> String
$cshow :: forall a. Show a => RGB a -> String
showsPrec :: Int -> RGB a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> RGB a -> ShowS
Show)

instance NFData a => NFData (RGB a)

-- TODO: Is this instance really necessary?
instance (Bounded a, Enum a) => Enum (RGB a) where
  fromEnum :: RGB a -> Int
fromEnum RGB a
rgb = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [ a -> Int
forall a. Enum a => a -> Int
fromEnum (RGB a -> a
forall a. RGB a -> a
red RGB a
rgb)
                     , a -> Int
forall a. Enum a => a -> Int
fromEnum (RGB a -> a
forall a. RGB a -> a
green RGB a
rgb) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
range
                     , a -> Int
forall a. Enum a => a -> Int
fromEnum (RGB a -> a
forall a. RGB a -> a
blue RGB a
rgb) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
range Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
range
                     ]
    where range :: Int
range = Int -> Int
forall a. Enum a => a -> a
succ (Int -> Int) -> (a -> Int) -> a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Int
forall a. Enum a => a -> Int
fromEnum (a -> Int) -> a -> Int
forall a b. (a -> b) -> a -> b
$ Bounded a => a
forall a. Bounded a => a
maxBound @a
  toEnum :: Int -> RGB a
toEnum Int
i = let (Int
b , Int
i') = Int
i Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`divMod` (Int
range Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
range)
                 (Int
g , Int
r) = Int
i' Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int
range
              in RGB :: forall a. a -> a -> a -> RGB a
RGB { red :: a
red = Int -> a
forall a. Enum a => Int -> a
toEnum Int
r
                     , green :: a
green = Int -> a
forall a. Enum a => Int -> a
toEnum Int
g
                     , blue :: a
blue = Int -> a
forall a. Enum a => Int -> a
toEnum Int
b
                     }
    where range :: Int
range = Int -> Int
forall a. Enum a => a -> a
succ (Int -> Int) -> (a -> Int) -> a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Int
forall a. Enum a => a -> Int
fromEnum (a -> Int) -> a -> Int
forall a b. (a -> b) -> a -> b
$ Bounded a => a
forall a. Bounded a => a
maxBound @a

instance Default (RGB Word8) where
  def :: RGB Word8
def = RGB :: forall a. a -> a -> a -> RGB a
RGB { red :: Word8
red = Word8
forall a. Bounded a => a
maxBound
            , green :: Word8
green = Word8
forall a. Bounded a => a
maxBound
            , blue :: Word8
blue = Word8
forall a. Bounded a => a
maxBound
            }