{-# LANGUAGE CPP                      #-}
{-# LANGUAGE ConstraintKinds          #-}
{-# LANGUAGE FlexibleContexts         #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE JavaScriptFFI            #-}
{-# LANGUAGE RankNTypes               #-}
{-# LANGUAGE RecursiveDo              #-}
{-# LANGUAGE ScopedTypeVariables      #-}
{-# LANGUAGE TemplateHaskell          #-}
{-# LANGUAGE TypeFamilies             #-}

module Reflex.Dom.Contrib.Router where

------------------------------------------------------------------------------
import           Control.Monad
import           Control.Monad.Trans
import           GHCJS.DOM
import           GHCJS.DOM.Document
import           GHCJS.DOM.Types (unWindow)
import           GHCJS.DOM.Window
import           GHCJS.DOM.HTMLDocument
#ifdef ghcjs_HOST_OS
import GHCJS.Foreign.Callback
import           GHCJS.Types
import           GHCJS.Prim
#endif
import           Prelude hiding (mapM, mapM_, all, sequence)
import           Reflex.Dom
import           Reflex.Dom.Contrib.Utils
------------------------------------------------------------------------------


------------------------------------------------------------------------------
setUrl
    :: MonadWidget t m
    => Event t String
    -> m ()
setUrl e = do
    performEvent_ $ ffor e $ \url -> liftIO $ do
        windowHistoryPushState url


------------------------------------------------------------------------------
getWindowLocation :: Window -> IO String
#ifdef ghcjs_HOST_OS
getWindowLocation w = do
    liftM fromJSString $ js_windowLocationPathname (unWindow w)

foreign import javascript unsafe
  "$1['location']['pathname']"
  js_windowLocationPathname :: JSVal -> IO JSVal
#else
getWindowLocation =
    error "getWindowLocation: only works in GHCJS"
#endif


------------------------------------------------------------------------------
setupHistoryHandler :: Window -> (String -> IO ()) -> IO ()
#ifdef ghcjs_HOST_OS
setupHistoryHandler w cb = do
    cbRef <- syncCallback1 ThrowWouldBlock (cb . fromJSString)
    js_setupHistoryHandler (unWindow w) cbRef

foreign import javascript unsafe
  "$1.onpopstate = function(event) { $2($1['location']['pathname']); }"
  js_setupHistoryHandler :: JSVal -> Callback (JSVal -> IO ()) -> IO ()
#else
setupHistoryHandler =
    error "setupHistoryHandler: only works in GHCJS"
#endif


------------------------------------------------------------------------------
-- | Handles routing for a site.  The argument to this function is a widget
-- function with the effective type signature `String -> m (Event t String)`.
-- The String parameter is the initial value of the window location pathname.
-- The return value is an event that updates the window location.
--routeSite
--    :: (forall t m a. (MonadWidget t m) => (String -> m (Event t String)))
--    -> IO ()
routeSite siteFunc = runWebGUI $ \webView -> do
    w <- waitUntilJust currentWindow
    path <- getWindowLocation w
    --setupHistoryHandler w (\arg -> putStrLn $ "ghcjs history handling!  " ++ arg)
    --wrapDomEvent w domWindowOnpopstate myGetEvent
    doc <- waitUntilJust $ liftM (fmap castToHTMLDocument) $
             webViewGetDomDocument webView
    body <- waitUntilJust $ getBody doc
    attachWidget body webView $ do
      changes <- siteFunc path
      setUrl changes
      return ()

--myGetEvent = do
--    e <- event
--    liftIO $ uiEventGetView e