{-# OPTIONS_GHC -fno-warn-orphans -F -pgmF trhsx #-}
import Control.Applicative
import Control.Applicative.Error
import Control.Monad
import Control.Monad.Trans
import Happstack.Server hiding (ContentType)
import Happstack.Server.HSP.HTML
import HSP.ServerPartT
import HSP
import qualified HSX.XMLGenerator as HSX
import Text.Formlets

-- |An input field with an optional value
input :: (XMLGenerator x, Monad v) => Maybe String -> Form [XMLGenT x (HSX.XML x)] v String
input = input' (\n v -> [<input type="text" id=n name=n value=v />])

-- |An input field with an optional value
password :: (XMLGenerator x, Monad v) => Maybe String -> Form [XMLGenT x (HSX.XML x)] v String
password = input' (\n v -> [<input type="password" id=n name=n value=v />])

submit :: (XMLGenerator x, Monad v) => String -> Form [XMLGenT x (HSX.XML x)] v String
submit value = input' (\n v -> [<input type="submit" name=n value=v />]) (Just value)



main = simpleHTTP nullConf impl

impl :: ServerPartT IO Response
impl =
    msum [ do methodM GET
              let (_, xml, _) = runFormState ([],[]) "" form
              page $
                <form action="/" method="POST" enctype="multipart/form-data;charset=UTF-8" accept-charset="UTF-8" >
                 <% xml %>
                </form>
         ,  do methodM POST
               (Just vals') <- getDataFn lookPairs
               let vals = map (\(n,v) -> (n, Left v)) vals'
               let (collector, _, _) = runFormState ([], vals) "" form
               res <- liftIO $ collector
               case res of
                 (SuccessAt a) -> page $ <p>You entered: <% show a %></p>
                 (FailureAt errs) ->
                     do let (_, xml, _) = runFormState (errs, vals) "" form
                        page $
                          <form action="/" method="POST" enctype="multipart/form-data;charset=UTF-8" accept-charset="UTF-8" >
--                           <% show vals' %>
--                           <% show errs %>
                           <% xml %>
                          </form>
         ]

page :: XMLGenT (ServerPartT IO) XML -> ServerPartT IO Response
page b = 
    do xml <- unXMLGenT $
               <html>
                <head>
                 <title>Fomlets Demo</title>
                </head>
                <body>
                 <% b %>
                </body>
               </html>
       ok (toResponse xml)


label str = xml $ [<label><% str %></label>]

br :: Form [XMLGenT (ServerPartT IO) (HSX.XML (ServerPartT IO))] IO ()
br = xml $ [<br />]
       
form :: Form [XMLGenT (ServerPartT IO) (HSX.XML (ServerPartT IO))] IO (String, String)
form =  (,) <$> (username <* br) <*> pass <* submit "create account"

username :: Form [XMLGenT (ServerPartT IO) (HSX.XML (ServerPartT IO))] IO String
username = 
    checkInline (label "Username" *> input Nothing)
                (\str -> if (length str) < 6 then 
                            Failure ["Your username must be at least 6 characters long."] 
                         else if (str == "foobar") then
                            Failure ["You may not use the username foobar."]
                         else Success str)
                (\errs xml ->
                     xml ++ (map (\err -> <span><% err %></span>) errs))

pass :: Form [XMLGenT (ServerPartT IO) (HSX.XML (ServerPartT IO))] IO String
pass = 
    checkInline ((,) <$> (label "Password" *> password Nothing <* br) <*>
                          (label "Confirm Password" *> password Nothing <* br))
                (\(str1, str2) -> 
                     if str1 /= str2 then 
                         Failure ["Passwords do not match."] 
                     else Success str1)
                (\errs xml ->
                     [<p>Passwords do not match.</p>] ++ xml
                )
