module Rules.Utility(rules) where
import RuleUtils
-- import GenUtil

rules :: [RuleDef]
rules = [("Query",queryGen, "Utility", "provide a QueryFoo class with 'is', 'has', 'from', and 'get' routines", Nothing) ]


queryGen :: Data -> Doc
queryGen d@D{name = name} = cls $$ text "" $$ ins where
    cls = text "class" <+> text className <+> typeName <+> cargs <+> text "where" $$ block fs
    ot a b = a <+> text "::" <+> b
    cargs = if null $ vars d then empty else dargs <+> text "|" <+> typeName <+> text "->" <+> dargs
    dargs =  hsep (map text $ vars d)
    className = "Query" ++ name
    typeName = text "_x"
    fs = (map is (body d) )
    is Body{constructor = constructor, types = types} = fn $$ dfn $$ ffn where
        fnName = text $ "is" ++ constructor
        fromName = "from" ++ constructor
        fn = ot fnName $  typeName <+> rArrow <+> text "Bool"
        dfn = fnName <+> x <+> text "=" <+> text "isJust" <+> parens (text fromName <+> x)
        ffn = ot (text fromName) $ text "Monad _m =>" <+> typeName <+> rArrow <+> text "_m" <+> tuple (map prettyType types)

    ins = text "instance" <+> text className <+> parens (text name <+> dargs) <+> dargs <+> text "where" $$ block fromInsts
    fromInsts = map fi (body d)
    fi Body{constructor = constructor, types = types} = fn $$ dfn where
        fromName = "from" ++ constructor
        fn = text fromName <+> pattern constructor types <+> text "=" <+> text "return" <+> tuple (varNames types)
        dfn = text fromName <+> blank <+> equals <+> text "fail" <+> tshow fromName

