-- © 2001, 2002 Peter Thiemann
-- |Defines the class 'CGIOutput' of data types that can be output from a CGI
-- program. 
module WASH.CGI.CGIOutput where

import IO
import Maybe
import Monad
import System

import WASH.Utility.Auxiliary
import WASH.Utility.BulkIO (rawHandleCopy)
import qualified WASH.CGI.Debug as Debug
import qualified WASH.Utility.RFC2279 as RFC2279

import qualified WASH.Utility.Shell as Shell

import WASH.CGI.CGIConfig
import WASH.CGI.CGITypes
import WASH.CGI.HTMLWrapper hiding (head, div, span, map)
import WASH.HTML.HTMLTemplates

-- import qualified PostElementAction

-- |(internal) takes an output handle and a document without forms and input
-- widgets, displays the document with suitable mime type and encoding, and
-- terminates the program
itell :: Handle -> WithHTML x IO () -> IO a
itell h hma = do elem <- build_document hma
		 cgiPut h elem
		 exitWith ExitSuccess

-- 
class CGIOutput a where
  cgiPut' :: Handle -> a -> IO ()
  cgiPutList :: Handle -> [a] -> IO ()
  
  cgiPutList h xs = cgiPutList h xs

cgiPut :: CGIOutput a => Handle -> a -> IO ()
cgiPut h x =
  do cgiPut' h x

instance CGIOutput a => CGIOutput [a] where
  cgiPut' h xs = cgiPutList h xs

-- instance CGIOutput Element where
instance CGIOutput ELEMENT_ where
  cgiPut' h x = hPutElement h x

instance CGIOutput Char where
  cgiPut' h ch = cgiPutList h [ch]
  cgiPutList h x = hPutListChar h x

instance CGIOutput FileReference where
  cgiPut' h x = hPutFileReference h x

instance CGIOutput ResponseFileReference where
  cgiPut' h x = hPutResponseFileReference h x

instance CGIOutput Status where
  cgiPut' h x = hPutStatus h x
	  
instance CGIOutput Location where
  cgiPut' h x = hPutLocation h x

instance CGIOutput FreeForm where
  cgiPut' h x = hPutFreeForm h x

-- ------------------------------------------------------------

hPutElement h elem =
    do hPutStrLn h "Content-Type: text/html; charset=utf-8"
       -- hPutStrLn h "Content-Type: application/xhtml+xml; charset=utf-8"
       -- This MIME type does not work with Mozilla 1.6. It says
       -- "This XML file does not appear to have any style information associated
       -- with it. The document tree is shown below."
       hPutStrLn h ""
       hPutStr h $ RFC2279.encode $ show elem
       -- PostElementAction.postElementAction h
       let new h = hPutStrLn h (showTemplatified elem "")
	   old h = hPutStrLn h $ RFC2279.encode $ show elem
       Debug.logOutput "OLD" old
       -- Debug.logOutput "NEW" new

hPutListChar h str =
    do hPutStrLn h "Content-Type: text/plain; charset=utf-8"
       hPutStrLn h ""
       hPutStr h $ RFC2279.encode str

hPutFileReference h fr =
    do hPutStr h "Content-Type: "
       hPutStrLn h (fileReferenceContentType fr)
       hPutStrLn h ""
       hFlush h
       hin <- openFile (fileReferenceName fr) ReadMode
       rawHandleCopy hin h
       hClose hin

hPutResponseFileReference h (ResponseFileReference fname) =
    do hFlush h
       hin <- openFile fname ReadMode
       rawHandleCopy hin h
       hClose hin

hPutStatus h (Status status reason_phrase elems) =
    do hPutStr h "Status: "
       hPutStr h status_str
       hPutStr h " "
       hPutStrLn h reason_phrase
       case elems of
         Nothing -> hPutStrLn h ""
	 Just _  -> itell h message
    where status_str = show status
	  ttl = "Error: " ++ status_str ++ ' ' : reason_phrase
	  message = standardPage ttl (fromJust elems)

hPutLocation h (Location url) =
    do hPutStr h "Location: "
       hPutStrLn h (unURL url)
       hPutStrLn h ""

hPutFreeForm h (FreeForm fileName contentType rawContents) =
    do hPutStr h "Content-Type: "
       hPutStr h contentType
       when (not (null fileName)) $
         do hPutStr h " ;name=\""
	    hPutStr h fileName
	    hPutStr h "\""
       hPutStrLn h ""
       hPutStrLn h ""
       hPutStr h rawContents