{-# LANGUAGE TemplateHaskell #-}

{-|
Module:             Filters
Description:        AWS Filter types.
Copyright:          © 2017 All rights reserved.
License:            GPL-3
Maintainer:         Evan Cofsky <evan@theunixman.com>
Stability:          experimental
Portability:        POSIX
-}

module Network.AWS.Machines.Filters where

import Lawless
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as M
import Data.Set (Set)
import qualified Data.Set as S
import Text hiding (text)
import Network.AWS.EC2
import Data.Word
import Numeric
import Textual

newtype Filters = Filters {unFilters  Map Text (Set Text)}
    deriving (Eq, Ord, Show)

filters  Getter Filters [Filter]
filters =
    to
    $ ifoldMap
    (\k v  [filter' k & fValues <>~ toListOf folded v])  unFilters

instance Monoid Filters where
    mempty = Filters M.empty
    a `mappend` b =
        Filters $ M.unionWith S.union (unFilters a) (unFilters b)

class IsFilter a where
    toFilters  Getter a Filters
    toFilters =
        let
            f a =
                Filters
                $ M.singleton
                (a ^. name)
                (a ^. values)
        in
            to f

    name  Getter a Text
    values  Getter a (Set Text)

newtype OwnerId = OwnerId {unOwnerId  Word64} deriving (Eq, Ord, Show)
newtype Name = Name {unName  Text} deriving (Eq, Ord, Show)
data EC2Tag = EC2Tag {
    _ectName  Text,
    _ectValues  Set Text
    } deriving (Eq, Ord, Show)
makeLenses ''EC2Tag

ec2Tag  Text  EC2Tag
ec2Tag = flip EC2Tag mempty

instance Printable OwnerId where
    print o =
        let
            s oid = showInt oid ""
            n oid = 12 - lengthOf traversed (s oid)
            p oid = '0' ^.. repeated ^.. taking (n oid) traversed
            v (OwnerId oid) = (p oid ++ s oid)
        in
            print $ v o

instance Printable EC2Tag where
    print (EC2Tag {..}) =
        let
            n = fsep ":" [text "tag", text _ectName]
            vs = fsep "," $ foldMapOf folded (flip (:) []  text) _ectValues
        in
            fsep (char '=') [n, vs]

instance IsFilter EC2Tag where
    name = to $ (\t  buildText $ text "tag:" <> text (t ^. ectName))
    values = to $ (view ectValues)

instance IsFilter ArchitectureValues where
    name = to $ const "architecture"
    values = to $
        \case
            I386  S.singleton "i386"
            X86_64  S.singleton "x86_64"

instance IsFilter VirtualizationType where
    name = to $ const "virtualization-type"
    values = to $
        \case
            HVM  S.singleton "hvm"
            Paravirtual  S.singleton "paravirtual"

instance IsFilter OwnerId where
    name = to $ const "owner-id"
    values =
        let
            s oid = showInt oid ""
            n oid = 12 - lengthOf traversed (s oid)
            p oid = '0' ^.. repeated ^.. taking (n oid) traversed
            v (OwnerId oid) = S.singleton $ (p oid ++ s oid) ^. packed
        in
            to v

instance IsFilter DeviceType where
    name = to $ const "root-device-type"
    values = to $
        \case
            EBS  S.singleton "ebs"
            InstanceStore  S.singleton "instance-store"

instance IsFilter Name where
    name = to $ const "name"
    values = to $ S.singleton  unName