{-# LANGUAGE QuasiQuotes, OverloadedStrings #-}
module Happstack.Authenticate.OpenId.Controllers where

import Control.Lens                       ((^.))
import Control.Monad.Trans                (MonadIO(..))
import Data.Acid                          (AcidState)
import Data.Acid.Advanced                 (query')
import Data.Maybe                         (fromMaybe)
import Data.Text                          (Text)
import qualified Data.Text                as T
import Happstack.Authenticate.Core        (AuthenticateState, AuthenticateURL, getToken, tokenIsAuthAdmin)
import Happstack.Authenticate.OpenId.Core (GetOpenIdRealm(..), OpenIdState)
import Happstack.Authenticate.OpenId.URL  (OpenIdURL(BeginDance, Partial, ReturnTo), nestOpenIdURL)
import Happstack.Authenticate.OpenId.PartialsURL (PartialURL(UsingYahoo, RealmForm))
import Happstack.Server                   (Happstack)
import Language.Javascript.JMacro
import Web.Routes

openIdCtrl
  :: (Happstack m) =>
     AcidState AuthenticateState
  -> AcidState OpenIdState
  -> RouteT AuthenticateURL m JStat
openIdCtrl :: AcidState AuthenticateState
-> AcidState OpenIdState -> RouteT AuthenticateURL m JStat
openIdCtrl AcidState AuthenticateState
authenticateState AcidState OpenIdState
openIdState  =
  RouteT OpenIdURL m JStat -> RouteT AuthenticateURL m JStat
forall (m :: * -> *) a.
RouteT OpenIdURL m a -> RouteT AuthenticateURL m a
nestOpenIdURL (RouteT OpenIdURL m JStat -> RouteT AuthenticateURL m JStat)
-> RouteT OpenIdURL m JStat -> RouteT AuthenticateURL m JStat
forall a b. (a -> b) -> a -> b
$
    do OpenIdURL -> [(Text, Maybe Text)] -> Text
fn <- RouteT OpenIdURL m (OpenIdURL -> [(Text, Maybe Text)] -> Text)
forall (m :: * -> *).
MonadRoute m =>
m (URL m -> [(Text, Maybe Text)] -> Text)
askRouteFn
       Maybe (Token, JWT VerifiedJWT)
mt <- AcidState AuthenticateState
-> RouteT OpenIdURL m (Maybe (Token, JWT VerifiedJWT))
forall (m :: * -> *).
Happstack m =>
AcidState AuthenticateState -> m (Maybe (Token, JWT VerifiedJWT))
getToken AcidState AuthenticateState
authenticateState
       Maybe Text
mRealm <- case Maybe (Token, JWT VerifiedJWT)
mt of
         (Just (Token
token, JWT VerifiedJWT
_))
           | Token
token Token -> Getting Bool Token Bool -> Bool
forall s a. s -> Getting a s a -> a
^. Getting Bool Token Bool
Lens' Token Bool
tokenIsAuthAdmin ->
               AcidState (EventState GetOpenIdRealm)
-> GetOpenIdRealm
-> RouteT OpenIdURL m (EventResult GetOpenIdRealm)
forall event (m :: * -> *).
(QueryEvent event, MonadIO m) =>
AcidState (EventState event) -> event -> m (EventResult event)
query' AcidState (EventState GetOpenIdRealm)
AcidState OpenIdState
openIdState GetOpenIdRealm
GetOpenIdRealm
           | Bool
otherwise -> Maybe Text -> RouteT OpenIdURL m (Maybe Text)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Text
forall a. Maybe a
Nothing
         Maybe (Token, JWT VerifiedJWT)
Nothing -> Maybe Text -> RouteT OpenIdURL m (Maybe Text)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Text
forall a. Maybe a
Nothing
       JStat -> RouteT OpenIdURL m JStat
forall (m :: * -> *) a. Monad m => a -> m a
return (JStat -> RouteT OpenIdURL m JStat)
-> JStat -> RouteT OpenIdURL m JStat
forall a b. (a -> b) -> a -> b
$ Maybe Text -> (OpenIdURL -> [(Text, Maybe Text)] -> Text) -> JStat
openIdCtrlJs Maybe Text
mRealm OpenIdURL -> [(Text, Maybe Text)] -> Text
fn

openIdCtrlJs
  :: Maybe Text
  -> (OpenIdURL -> [(Text, Maybe Text)] -> Text)
  -> JStat
openIdCtrlJs :: Maybe Text -> (OpenIdURL -> [(Text, Maybe Text)] -> Text) -> JStat
openIdCtrlJs Maybe Text
mRealm OpenIdURL -> [(Text, Maybe Text)] -> Text
showURL =
  [jmacro|
   var openId = angular.module('openId', ['happstackAuthentication']);
   var openIdWindow;
   tokenCB = function (token) { alert('tokenCB: ' + token); };

   openId.controller('OpenIdCtrl', ['$scope','$http','$window', '$location', 'userService', function ($scope, $http, $window, $location, userService)
     { $scope.openIdRealm = { srOpenIdRealm: `(fromMaybe "" mRealm)` };

       $scope.openIdWindow = function (providerUrl) {
         tokenCB = function(token) { var u = userService.updateFromToken(token); $scope.isAuthenticated = u.isAuthenticated; $scope.$apply(); };
         openIdWindow = window.open(providerUrl, "_blank", "toolbar=0");
       };

       $scope.setOpenIdRealm = function (setRealmUrl) {
         function callback(datum, status, headers, config) {
           if (datum == null) {
             $scope.username_password_error = 'error communicating with the server.';
           } else {
             if (datum.jrStatus == "Ok") {
               $scope.set_openid_realm_msg = 'Realm Updated.'; // FIXME -- I18N
//               $scope.openIdRealm = '';
             } else {
               $scope.set_open_id_realm_msg = datum.jrData;
             }
           }
         };

         $http.post(setRealmUrl, $scope.openIdRealm).
           success(callback).
           error(callback);
       };
     }]);

   openId.directive('openidYahoo', ['$rootScope', function ($rootScope) {
     return {
       restrict: 'E',
       replace: true,
       templateUrl: `(showURL (Partial UsingYahoo) [])`
     };
   }]);

   openId.directive('openidRealm', ['$rootScope', function ($rootScope) {
     return {
       restrict: 'E',
       templateUrl: `(showURL (Partial RealmForm) [])`
     };
   }]);
  |]