{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell #-}

module Data.Aviation.Stratux.Types.EmitterCategory(
  EmitterCategory(..)
, AsEmitterCategory(..)
) where

import Control.Lens(Prism', prism', makeClassyPrisms, (^?), ( # ))
import Control.Monad(mzero, Monad(return))
import Data.Aeson(FromJSON(parseJSON), ToJSON(toJSON), Value(Number), withScientific)
import Data.Eq(Eq)
import Data.Int(Int)
import Data.Maybe(Maybe(Just, Nothing))
import Data.Ord(Ord)
import Data.Scientific(Scientific)
import Data.Word(Word)
import Prelude(Show, Num, Integer, Float, Double)

-- $setup
-- >>> :set -XOverloadedStrings
-- >>> import Control.Lens
-- >>> import Data.Aeson(decode, encode)
-- >>> import Data.Maybe(Maybe)
-- >>> import Prelude

-- https://i.imgur.com/cXYhzZM.png
data EmitterCategory = -- 0 to 7
  NoEmitterCategory
  | Light -- < 15500lb
  | Small -- 15500-75000lb
  | Large -- 75000-300000lb
  | HighVortexLarge -- B757
  | Heavy -- > 300000lb
  | HighPerformance -- >5G accel ^ > 400KIAS
  | Rotorcraft
  deriving (Eq, Ord, Show)

makeClassyPrisms ''EmitterCategory

-- |
--
-- >>> _EmitterCategory # NoEmitterCategory :: Scientific
-- 0.0
--
-- >>> _EmitterCategory # Light :: Scientific
-- 1.0
--
-- >>> _EmitterCategory # HighVortexLarge :: Scientific
-- 4.0
--
-- >>> _EmitterCategory # Rotorcraft :: Scientific
-- 7.0
instance AsEmitterCategory Scientific where
  _EmitterCategory =
    emitterCategoryNum

-- |
--
-- >>> _EmitterCategory # NoEmitterCategory :: Int
-- 0
--
-- >>> _EmitterCategory # Light :: Int
-- 1
--
-- >>> _EmitterCategory # HighVortexLarge :: Int
-- 4
--
-- >>> _EmitterCategory # Rotorcraft :: Int
-- 7
instance AsEmitterCategory Int where
  _EmitterCategory =
    emitterCategoryNum

-- |
--
-- >>> _EmitterCategory # NoEmitterCategory :: Integer
-- 0
--
-- >>> _EmitterCategory # Light :: Integer
-- 1
--
-- >>> _EmitterCategory # HighVortexLarge :: Integer
-- 4
--
-- >>> _EmitterCategory # Rotorcraft :: Integer
-- 7
instance AsEmitterCategory Integer where
  _EmitterCategory =
    emitterCategoryNum

-- |
--
-- >>> _EmitterCategory # NoEmitterCategory :: Float
-- 0.0
--
-- >>> _EmitterCategory # Light :: Float
-- 1.0
--
-- >>> _EmitterCategory # HighVortexLarge :: Float
-- 4.0
--
-- >>> _EmitterCategory # Rotorcraft :: Float
-- 7.0
instance AsEmitterCategory Float where
  _EmitterCategory =
    emitterCategoryNum

-- |
--
-- >>> _EmitterCategory # NoEmitterCategory :: Double
-- 0.0
--
-- >>> _EmitterCategory # Light :: Double
-- 1.0
--
-- >>> _EmitterCategory # HighVortexLarge :: Double
-- 4.0
--
-- >>> _EmitterCategory # Rotorcraft :: Double
-- 7.0
instance AsEmitterCategory Double where
  _EmitterCategory =
    emitterCategoryNum

-- |
--
-- >>> _EmitterCategory # NoEmitterCategory :: Word
-- 0
--
-- >>> _EmitterCategory # Light :: Word
-- 1
--
-- >>> _EmitterCategory # HighVortexLarge :: Word
-- 4
--
-- >>> _EmitterCategory # Rotorcraft :: Word
-- 7
instance AsEmitterCategory Word where
  _EmitterCategory =
    emitterCategoryNum

emitterCategoryNum ::
  (Num a, Eq a) =>
  Prism'
    a
    EmitterCategory
emitterCategoryNum =
  prism'
    (\t ->  case t of
              NoEmitterCategory ->
                0
              Light ->
                1
              Small ->
                2
              Large ->
                3
              HighVortexLarge ->
                4
              Heavy ->
                5
              HighPerformance ->
                6
              Rotorcraft ->
                7) 
    (\n ->  case n of
              0 ->
                Just NoEmitterCategory
              1 ->
                Just Light
              2 ->
                Just Small
              3 -> 
                Just Large
              4 ->
                Just HighVortexLarge
              5 ->
                Just Heavy
              6 ->
                Just HighPerformance
              7 ->
                Just Rotorcraft
              _ ->
                Nothing)

-- |
--
-- >>> decode "0" :: Maybe EmitterCategory
-- Just NoEmitterCategory
--
-- >>> decode "1" :: Maybe EmitterCategory
-- Just Light
--
-- >>> decode "4" :: Maybe EmitterCategory
-- Just HighVortexLarge
--
-- >>> decode "7" :: Maybe EmitterCategory
-- Just Rotorcraft
instance FromJSON EmitterCategory where
  parseJSON =
    withScientific "EmitterCategory" (\n -> case n ^? _EmitterCategory of
      Nothing ->
        mzero
      Just t ->
        return t)
-- |
--
-- >>> encode NoEmitterCategory
-- "0"
--
-- >>> encode Light
-- "1"
--
-- >>> encode HighVortexLarge
-- "4"
--
-- >>> encode Rotorcraft
-- "7"
instance ToJSON EmitterCategory where
  toJSON c =
    Number (_EmitterCategory # c)