{-# LANGUAGE OverloadedStrings #-}

-- |
-- Module       : Web.Skell.Saferoute
-- Description  : Saferoutes for things
-- Copyright    : 2014, Peter Harpending.
-- License      : BSD3
-- Maintainer   : Peter Harpending <pharpend2@gmail.com>
-- Stability    : experimental
-- Portability  : archlinux
--

module Web.Skell.Saferoute where

import qualified Data.Map.Lazy       as M
import           Data.Monoid
import qualified Data.Text           as S
import qualified Data.Text.Lazy      as L
import           Network.Wai (Response)
import           Paths_skell
import qualified Text.Blaze.Html5    as H
import           Web.Skell.Responsible

-- |The type for a route - just an alias for 'L.Text'
type Route = L.Text

-- |The type class for a resource.
class Eq r => Resource r where
  {-# MINIMAL getRoute, (resourceList | routeResourceMap) #-}

  -- Get the 'Route' for a 'Resource'. This is in place to avoid
  -- @fmap@ stuff. Giving a 'Resource' to this function will
  -- invariably return a 'Route', as opposed to 'Maybe Route', which
  -- would be the case if I used a 'M.Map' lookup.
  getRoute :: r -> Route

  -- |A list of all of the constructors for your resource type.
  resourceList :: [r]
  resourceList = M.elems routeResourceMap

  -- |A map from a route to it's resource.
  routeResourceMap :: M.Map Route r
  routeResourceMap = M.fromList [(route, resource) | resource <- resourceList,
                                                     let route = getRoute resource ]

  -- |Given a 'Route', find the 'Resource' behind it. If the route
  -- isn't associated with any 'Resource', this returns 'Nothing'.
  lookupRoute :: Route -> Maybe r
  lookupRoute route = M.lookup route routeResourceMap

  getUrl :: Resource r => r -> H.AttributeValue
  getUrl = H.toValue . getRoute

-- |Intercalate slashes, and add one to the front
slashPrependJoin :: [S.Text] -> S.Text
slashPrependJoin parts = "/" <> S.intercalate "/" parts