-- | Haskell project name generation
-- semi-joke
module Lambdabot.Plugin.Misc.Fresh (freshPlugin) where

import Lambdabot.Plugin

import Control.Monad.Trans
import Data.Char

type Fresh = ModuleT Integer LB

freshPlugin :: Module Integer
freshPlugin :: Module Integer
freshPlugin = Module Integer
forall st. Module st
newModule
    { moduleDefState :: LB Integer
moduleDefState = Integer -> LB Integer
forall (m :: * -> *) a. Monad m => a -> m a
return Integer
0
    , moduleSerialize :: Maybe (Serial Integer)
moduleSerialize = Serial Integer -> Maybe (Serial Integer)
forall a. a -> Maybe a
Just Serial Integer
forall s. (Show s, Read s) => Serial s
stdSerial
    
    , moduleCmds :: ModuleT Integer LB [Command (ModuleT Integer LB)]
moduleCmds = [Command (ModuleT Integer LB)]
-> ModuleT Integer LB [Command (ModuleT Integer LB)]
forall (m :: * -> *) a. Monad m => a -> m a
return
        [ (String -> Command Identity
command String
"freshname")
            { help :: Cmd (ModuleT Integer LB) ()
help = String -> Cmd (ModuleT Integer LB) ()
forall (m :: * -> *). Monad m => String -> Cmd m ()
say String
"freshname. Return a unique Haskell project name."
            , process :: String -> Cmd (ModuleT Integer LB) ()
process = \String
_ -> ModuleT Integer LB String -> Cmd (ModuleT Integer LB) String
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ModuleT Integer LB String
fresh Cmd (ModuleT Integer LB) String
-> (String -> Cmd (ModuleT Integer LB) ())
-> Cmd (ModuleT Integer LB) ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> Cmd (ModuleT Integer LB) ()
forall (m :: * -> *). Monad m => String -> Cmd m ()
say
            }
        ]
    }

fresh :: Fresh String
fresh :: ModuleT Integer LB String
fresh = (LBState (ModuleT Integer LB)
 -> (LBState (ModuleT Integer LB) -> ModuleT Integer LB ())
 -> ModuleT Integer LB String)
-> ModuleT Integer LB String
forall (m :: * -> *) a.
MonadLBState m =>
(LBState m -> (LBState m -> m ()) -> m a) -> m a
withMS ((LBState (ModuleT Integer LB)
  -> (LBState (ModuleT Integer LB) -> ModuleT Integer LB ())
  -> ModuleT Integer LB String)
 -> ModuleT Integer LB String)
-> (LBState (ModuleT Integer LB)
    -> (LBState (ModuleT Integer LB) -> ModuleT Integer LB ())
    -> ModuleT Integer LB String)
-> ModuleT Integer LB String
forall a b. (a -> b) -> a -> b
$ \LBState (ModuleT Integer LB)
n LBState (ModuleT Integer LB) -> ModuleT Integer LB ()
f -> do
    LBState (ModuleT Integer LB) -> ModuleT Integer LB ()
f (Integer
LBState (ModuleT Integer LB)
nInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1)
    String -> ModuleT Integer LB String
forall (m :: * -> *) a. Monad m => a -> m a
return (String
"Ha" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
forall a. [a] -> [a]
reverse (Integer -> String
asName Integer
LBState (ModuleT Integer LB)
n))

asName :: Integer -> String
asName :: Integer -> String
asName Integer
i
    | Integer
i Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0    = [Int -> Char
chr (Char -> Int
ord Char
'a')]
    | Integer
r Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0    = [Int -> Char
chr (Char -> Int
ord Char
'a' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
a))]
    | Bool
otherwise =  Int -> Char
chr (Char -> Int
ord Char
'a' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
a)) Char -> String -> String
forall a. a -> [a] -> [a]
: Integer -> String
asName Integer
r
    where
      (Integer
r,Integer
a) = Integer
i Integer -> Integer -> (Integer, Integer)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Integer
26