package com.composum.platform.services.setup;

import com.composum.sling.core.service.RepositorySetupService;
import com.composum.sling.core.setup.util.SetupUtil;
import com.composum.sling.core.usermanagement.core.UserManagementService;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.vault.packaging.InstallContext;
import org.apache.jackrabbit.vault.packaging.InstallHook;
import org.apache.jackrabbit.vault.packaging.PackageException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.RepositoryException;
import javax.jcr.Session;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@SuppressWarnings("Duplicates")
public class SetupHook implements InstallHook {

    private static final Logger LOG = LoggerFactory.getLogger(SetupHook.class);

    public static final String PLATFORM_VERSION = "1.0.0.SNAPSHOT";

    private static final String EVERYONE_ACLS = "/conf/composum/platform/security/acl/everyone.json";
    private static final String ADMIN_ACLS = "/conf/composum/platform/security/acl/administrators.json";

    private static final String ADMINISTRATORS_GROUP = "administrators";

    public static final String PLATFORM_USERS_PATH = "composum/platform/";
    public static final String PLATFORM_SYSTEM_USERS_PATH = "system/composum/platform/";

    public static final String PLATFORM_ADMINISTRATORS = "composum-platform-administrators";
    public static final String PLATFORM_SERVICE_USER = "composum-platform-service";

    public static final Map<String, List<String>> PLATFORM_USERS;
    public static final Map<String, List<String>> PLATFORM_SYSTEM_USERS;
    public static final Map<String, List<String>> PLATFORM_GROUPS;

    static {
        PLATFORM_USERS = new LinkedHashMap<>();
        PLATFORM_SYSTEM_USERS = new LinkedHashMap<>();
        PLATFORM_SYSTEM_USERS.put(PLATFORM_SYSTEM_USERS_PATH + PLATFORM_SERVICE_USER, Collections.singletonList(
                PLATFORM_ADMINISTRATORS
        ));
        PLATFORM_GROUPS = new LinkedHashMap<>();
        PLATFORM_GROUPS.put(PLATFORM_USERS_PATH + PLATFORM_ADMINISTRATORS, Collections.singletonList(
                PLATFORM_SERVICE_USER
        ));
    }

    @Override
    public void execute(InstallContext ctx) throws PackageException {
        switch (ctx.getPhase()) {
            case PREPARE:
                LOG.info("prepare: execute...");
                setupGroupsAndUsers(ctx);
                LOG.info("prepare: execute ends.");
                break;
            case INSTALLED:
                LOG.info("installed: execute...");
                setupAcls(ctx);
                SetupUtil.checkBundles(ctx, new HashMap<String, String>() {{
                    put("com.composum.platform.staging", PLATFORM_VERSION);
                    put("com.composum.platform.security", PLATFORM_VERSION);
                }}, 2, 30);
                LOG.info("installed: execute ends.");
                break;
        }
    }

    protected void setupGroupsAndUsers(InstallContext ctx) {
        UserManagementService userManagementService = SetupUtil.getService(UserManagementService.class);
        try {
            JackrabbitSession session = (JackrabbitSession) ctx.getSession();
            UserManager userManager = session.getUserManager();
            for (Map.Entry<String, List<String>> entry : PLATFORM_GROUPS.entrySet()) {
                Group group = userManagementService.getOrCreateGroup(session, userManager, entry.getKey());
                if (group != null) {
                    for (String memberName : entry.getValue()) {
                        userManagementService.assignToGroup(session, userManager, memberName, group);
                    }
                }
            }
            session.save();
            for (Map.Entry<String, List<String>> entry : PLATFORM_SYSTEM_USERS.entrySet()) {
                Authorizable user = userManagementService.getOrCreateUser(session, userManager, entry.getKey(), true);
                if (user != null) {
                    for (String groupName : entry.getValue()) {
                        userManagementService.assignToGroup(session, userManager, user, groupName);
                    }
                }
            }
            session.save();
            for (Map.Entry<String, List<String>> entry : PLATFORM_USERS.entrySet()) {
                Authorizable user = userManagementService.getOrCreateUser(session, userManager, entry.getKey(), false);
                if (user != null) {
                    for (String groupName : entry.getValue()) {
                        userManagementService.assignToGroup(session, userManager, user, groupName);
                    }
                }
            }
            session.save();
        } catch (RepositoryException rex) {
            LOG.error(rex.getMessage(), rex);
        }
    }

    protected void setupAcls(InstallContext ctx) {
        RepositorySetupService setupService = SetupUtil.getService(RepositorySetupService.class);
        try {
            Session session = ctx.getSession();
            setupService.addJsonAcl(session, EVERYONE_ACLS, null);
            setupService.addJsonAcl(session, ADMIN_ACLS, null);
            session.save();
        } catch (RepositoryException | IOException rex) {
            LOG.error(rex.getMessage(), rex);
        }
    }
}

@@ -160,309 +160,8 @@
 il;%0A
-import com.composum.sling.core.usermanagement.core.UserManagementService;%0Aimport org.apache.jackrabbit.api.JackrabbitSession;%0Aimport org.apache.jackrabbit.api.security.user.Authorizable;%0Aimport org.apache.jackrabbit.api.security.user.Group;%0Aimport org.apache.jackrabbit.api.security.user.UserManager;%0A
 impo
@@ -217,16 +217,16 @@
 ontext;%0A
+
 import o
@@ -2379,24 +2379,34 @@
             
+SetupUtil.
 setupGroupsA
@@ -2412,24 +2412,80 @@
 AndUsers(ctx
+, PLATFORM_GROUPS, PLATFORM_SYSTEM_USERS, PLATFORM_USERS
 );%0A         
@@ -2965,32 +2965,32 @@
 xecute ends.%22);%0A
+
                 
@@ -3017,1900 +3017,8 @@
  %7D%0A%0A
-    protected void setupGroupsAndUsers(InstallContext ctx) %7B%0A        UserManagementService userManagementService = SetupUtil.getService(UserManagementService.class);%0A        try %7B%0A            JackrabbitSession session = (JackrabbitSession) ctx.getSession();%0A            UserManager userManager = session.getUserManager();%0A            for (Map.Entry%3CString, List%3CString%3E%3E entry : PLATFORM_GROUPS.entrySet()) %7B%0A                Group group = userManagementService.getOrCreateGroup(session, userManager, entry.getKey());%0A                if (group != null) %7B%0A                    for (String memberName : entry.getValue()) %7B%0A                        userManagementService.assignToGroup(session, userManager, memberName, group);%0A                    %7D%0A                %7D%0A            %7D%0A            session.save();%0A            for (Map.Entry%3CString, List%3CString%3E%3E entry : PLATFORM_SYSTEM_USERS.entrySet()) %7B%0A                Authorizable user = userManagementService.getOrCreateUser(session, userManager, entry.getKey(), true);%0A                if (user != null) %7B%0A                    for (String groupName : entry.getValue()) %7B%0A                        userManagementService.assignToGroup(session, userManager, user, groupName);%0A                    %7D%0A                %7D%0A            %7D%0A            session.save();%0A            for (Map.Entry%3CString, List%3CString%3E%3E entry : PLATFORM_USERS.entrySet()) %7B%0A                Authorizable user = userManagementService.getOrCreateUser(session, userManager, entry.getKey(), false);%0A                if (user != null) %7B%0A                    for (String groupName : entry.getValue()) %7B%0A                        userManagementService.assignToGroup(session, userManager, user, groupName);%0A                    %7D%0A                %7D%0A            %7D%0A            session.save();%0A        %7D catch (RepositoryException rex) %7B%0A            LOG.error(rex.getMessage(), rex);%0A        %7D%0A    %7D%0A%0A
     

package setup hook implementation - code cleanup