{-# LANGUAGE GeneralizedNewtypeDeriving, RankNTypes, ScopedTypeVariables #-}

module SemigroupPresentation.Generator (
    Generator,
    generator,
    numGenerator,
    GWord,
    StrGWord,
    filterByFormat,
    matchWithFormat,
    insertGen,
  ) where

import Format
import Containers
import Lens

import Data.Maybe (mapMaybe)

newtype Generator = G { Generator -> Int
numGenerator :: Int }
    deriving (Generator -> Generator -> Bool
(Generator -> Generator -> Bool)
-> (Generator -> Generator -> Bool) -> Eq Generator
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Generator -> Generator -> Bool
$c/= :: Generator -> Generator -> Bool
== :: Generator -> Generator -> Bool
$c== :: Generator -> Generator -> Bool
Eq, Eq Generator
Eq Generator
-> (Generator -> Generator -> Ordering)
-> (Generator -> Generator -> Bool)
-> (Generator -> Generator -> Bool)
-> (Generator -> Generator -> Bool)
-> (Generator -> Generator -> Bool)
-> (Generator -> Generator -> Generator)
-> (Generator -> Generator -> Generator)
-> Ord Generator
Generator -> Generator -> Bool
Generator -> Generator -> Ordering
Generator -> Generator -> Generator
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
min :: Generator -> Generator -> Generator
$cmin :: Generator -> Generator -> Generator
max :: Generator -> Generator -> Generator
$cmax :: Generator -> Generator -> Generator
>= :: Generator -> Generator -> Bool
$c>= :: Generator -> Generator -> Bool
> :: Generator -> Generator -> Bool
$c> :: Generator -> Generator -> Bool
<= :: Generator -> Generator -> Bool
$c<= :: Generator -> Generator -> Bool
< :: Generator -> Generator -> Bool
$c< :: Generator -> Generator -> Bool
compare :: Generator -> Generator -> Ordering
$ccompare :: Generator -> Generator -> Ordering
$cp1Ord :: Eq Generator
Ord, Int -> Generator
Generator -> Int
Generator -> [Generator]
Generator -> Generator
Generator -> Generator -> [Generator]
Generator -> Generator -> Generator -> [Generator]
(Generator -> Generator)
-> (Generator -> Generator)
-> (Int -> Generator)
-> (Generator -> Int)
-> (Generator -> [Generator])
-> (Generator -> Generator -> [Generator])
-> (Generator -> Generator -> [Generator])
-> (Generator -> Generator -> Generator -> [Generator])
-> Enum Generator
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Generator -> Generator -> Generator -> [Generator]
$cenumFromThenTo :: Generator -> Generator -> Generator -> [Generator]
enumFromTo :: Generator -> Generator -> [Generator]
$cenumFromTo :: Generator -> Generator -> [Generator]
enumFromThen :: Generator -> Generator -> [Generator]
$cenumFromThen :: Generator -> Generator -> [Generator]
enumFrom :: Generator -> [Generator]
$cenumFrom :: Generator -> [Generator]
fromEnum :: Generator -> Int
$cfromEnum :: Generator -> Int
toEnum :: Int -> Generator
$ctoEnum :: Int -> Generator
pred :: Generator -> Generator
$cpred :: Generator -> Generator
succ :: Generator -> Generator
$csucc :: Generator -> Generator
Enum)

instance Bounded Generator where
    minBound :: Generator
minBound = Int -> Generator
G Int
0
    maxBound :: Generator
maxBound = Int -> Generator
G Int
forall a. Bounded a => a
maxBound

generator :: Int -> Generator
generator :: Int -> Generator
generator = Int -> Generator
G

type GWord = [Generator]

type StrGWord = [String]

filterByFormat :: String -> Getter (Set String) (Set String)
filterByFormat :: String -> Getter (Set String) (Set String)
filterByFormat String
s = (Set String -> Set String)
-> Optic' (->) f (Set String) (Set String)
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to ((Set String -> Set String)
 -> Optic' (->) f (Set String) (Set String))
-> (Set String -> Set String)
-> Optic' (->) f (Set String) (Set String)
forall a b. (a -> b) -> a -> b
$
    case String -> Maybe SimpleFormat
forall f (m :: * -> *). (Format f, MonadFail m) => String -> m f
format String
s :: Maybe SimpleFormat of
        Maybe SimpleFormat
Nothing -> Set String -> Set String -> Set String
forall a b. a -> b -> a
const Set String
forall c. Nullable c => c
emptyC
        Just SimpleFormat
f  -> (String -> Bool) -> Set String -> Set String
forall c v. Filterable c v => (v -> Bool) -> c -> c
filterC ((String -> Bool) -> Set String -> Set String)
-> (String -> Bool) -> Set String -> Set String
forall a b. (a -> b) -> a -> b
$ SimpleFormat -> String -> Bool
forall f r. Match f r => f -> String -> r
match SimpleFormat
f

matchWithFormat :: String -> Getter (Set String) (Set String)
matchWithFormat :: String -> Getter (Set String) (Set String)
matchWithFormat String
s = (Set String -> Set String)
-> Optic' (->) f (Set String) (Set String)
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to (
    [String] -> Set String
forall c v. UnsafeListable c v => [v] -> c
fromList ([String] -> Set String)
-> (Set String -> [String]) -> Set String -> Set String
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    (String -> Maybe String) -> [String] -> [String]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (\String
s' -> do
        SimpleFormat
f :: SimpleFormat <- String -> Maybe SimpleFormat
forall f (m :: * -> *). (Format f, MonadFail m) => String -> m f
format String
s
        SimpleFormat -> String -> Maybe String
forall f r. Match f r => f -> String -> r
match SimpleFormat
f String
s'
      ) ([String] -> [String])
-> (Set String -> [String]) -> Set String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    Set String -> [String]
forall c v. Listable c v => c -> [v]
toList
  )

insertGen :: String -> Getter (Set String) (Set String)
insertGen :: String -> Getter (Set String) (Set String)
insertGen = (Set String -> Set String)
-> Optic' (->) f (Set String) (Set String)
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to ((Set String -> Set String)
 -> Optic' (->) f (Set String) (Set String))
-> (String -> Set String -> Set String)
-> String
-> Optic' (->) f (Set String) (Set String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Set String -> Set String
forall c v. Insertable c v => v -> c -> c
(+>)