/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat Middleware LLC, and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jboss.aerogear.unifiedpush.test;

import org.keycloak.models.ClaimMask;
import org.keycloak.models.jpa.entities.OAuthClientEntity;
import org.keycloak.models.jpa.entities.RealmEntity;
import org.keycloak.models.jpa.entities.RoleEntity;
import org.keycloak.models.jpa.entities.ScopeMappingEntity;
import org.keycloak.models.jpa.entities.UserEntity;
import org.keycloak.models.jpa.entities.UserRequiredActionEntity;
import org.keycloak.models.utils.KeycloakModelUtils;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Class which handles configuration of the keycloak so its testable.
 */
@Stateless
public class KeycloakConfigurator {
    private static final Logger LOGGER = Logger.getLogger(KeycloakConfigurator.class.getName());

    @PersistenceContext(unitName = "keycloak-default")
    EntityManager entityManager;

    /**
     * Changes keycloak configuration to allow rest login and removes all required actions for all users in the
     * `aerogear` realm/
     */
    public KeycloakConfigurationResult configureForIntegrationTests() {
        KeycloakConfigurationResult result = new KeycloakConfigurationResult();

        TypedQuery<RealmEntity> realmQuery = entityManager.createNamedQuery("getRealmByName", RealmEntity.class);
        realmQuery.setParameter("name", "aerogear");

        for (RealmEntity realm : realmQuery.getResultList()) {
            LOGGER.warning("Editing realm: " + realm.getName());
            result.foundRealms.add(realm.getName() + ":" + realm.getId());
            TypedQuery<UserEntity> userQuery = entityManager.createNamedQuery("getAllUsersByRealm", UserEntity.class);
            userQuery.setParameter("realmId", realm.getId());

            // Enable Direct Grant API
            realm.setPasswordCredentialGrantAllowed(true);

            // Make sure the session won't expire even when the testing runs very slow
            realm.setAccessTokenLifespan(3600);
            realm.setAccessCodeLifespan(3600);
            realm.setAccessCodeLifespanUserAction(3600);
            realm.setSsoSessionIdleTimeout(3600);

            // Any required action would prevent us to login
            for (UserEntity user : userQuery.getResultList()) {
                LOGGER.log(Level.INFO, "Editing user: {0}", user.getUsername());
                result.foundUsers.add(user.getUsername());
                for (UserRequiredActionEntity userRequiredAction : user.getRequiredActions()) {
                    LOGGER.log(Level.INFO, "Removing required action: {0}", userRequiredAction.getAction().name());
                    String current = result.removedRequiredActions.get(user.getUsername());
                    result.removedRequiredActions.put(user.getUsername(), current + userRequiredAction.getAction().name() + ", ");
                    entityManager.remove(userRequiredAction);
                }
                user.getRequiredActions().clear();
            }

            OAuthClientEntity oAuthClient = new OAuthClientEntity();
            oAuthClient.setId(KeycloakModelUtils.generateId());
            oAuthClient.setName("integration-tests");
            oAuthClient.setEnabled(true);
            oAuthClient.setPublicClient(true);
            oAuthClient.setDirectGrantsOnly(true);
            oAuthClient.setAllowedClaimsMask(ClaimMask.USERNAME);
            oAuthClient.setRealm(realm);
            entityManager.persist(oAuthClient);

            for (RoleEntity roleEntity : realm.getRoles()) {
                result.roles.add(roleEntity.getName());
                ScopeMappingEntity scopemapping = new ScopeMappingEntity();
                scopemapping.setClient(oAuthClient);
                scopemapping.setRole(roleEntity);
                entityManager.persist(scopemapping);
            }
        }

        return result;
    }

    public static class KeycloakConfigurationResult {
        private List<String> foundRealms = new ArrayList<String>();
        private List<String> foundUsers = new ArrayList<String>();
        private Map<String, String> removedRequiredActions = new HashMap<String, String>();
        private List<String> roles = new ArrayList<String>();
    }
}

@@ -3971,32 +3971,492 @@
 %0A            %7D%0A%0A
+            TypedQuery%3COAuthClientEntity%3E existingEntityQuery =%0A                    entityManager.createNamedQuery(%22findOAuthClientByName%22, OAuthClientEntity.class);%0A            existingEntityQuery.setParameter(%22name%22, %22integration-tests%22);%0A            existingEntityQuery.setParameter(%22realm%22, realm);%0A%0A            // TODO should we instead remove all the oauthClients and create a new one?%0A            if(existingEntityQuery.getResultList().isEmpty()) %7B%0A    
             OAut
@@ -4500,32 +4500,36 @@
 ClientEntity();%0A
+    
             oAut
@@ -4572,24 +4572,28 @@
 erateId());%0A
+    
             
@@ -4638,32 +4638,36 @@
 %22);%0A            
+    
 oAuthClient.setE
@@ -4672,32 +4672,36 @@
 tEnabled(true);%0A
+    
             oAut
@@ -4735,32 +4735,36 @@
 e);%0A            
+ 
+   
 oAuthClient.setD
@@ -4778,32 +4778,36 @@
 antsOnly(true);%0A
+    
             oAut
@@ -4860,32 +4860,36 @@
 E);%0A            
+ 
+   
 oAuthClient.setR
@@ -4901,16 +4901,20 @@
 realm);%0A
+    
         
@@ -4962,24 +4962,28 @@
             
+ 
+   
 for (RoleEnt
@@ -5027,32 +5027,36 @@
                 
+    
 result.roles.add
@@ -5095,16 +5095,20 @@
         
+ 
+   
 ScopeMap
@@ -5167,32 +5167,36 @@
                 
+    
 scopemapping.set
@@ -5224,32 +5224,36 @@
                 
+  
+  
 scopemapping.set
@@ -5270,16 +5270,20 @@
 ntity);%0A
+    
         
@@ -5327,16 +5327,34 @@
 pping);%0A
+                %7D%0A
         

Add check if OAuthClient integration-tests already exists.