/*
 * Copyright The WildFly Authors
 * SPDX-License-Identifier: Apache-2.0
 */
package org.wildfly.test.jmx;

import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.BYTES;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ENABLED;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REMOVE;
import static org.jboss.as.test.integration.management.util.ModelUtil.createOpNode;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilePermission;
import java.io.IOException;
import java.io.InputStream;
import java.security.Permission;
import java.util.HashSet;
import java.util.Set;

import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.as.protocol.StreamUtils;
import org.jboss.as.test.integration.management.rbac.Outcome;
import org.jboss.as.test.integration.management.rbac.RbacUtil;
import org.jboss.as.test.shared.TestSuiteEnvironment;
import org.jboss.dmr.ModelNode;
import org.wildfly.core.testrunner.ManagementClient;
import org.wildfly.core.testrunner.ServerSetupTask;

/**
 *
 * @author <a href="mailto:ehugonne@redhat.com">Emmanuel Hugonnet</a> (c) 2014 Red Hat, inc.
 */
public class JMXListenerDeploymentSetupTask implements ServerSetupTask {
    public static final String TARGET_OBJECT_NAME = "jboss.root:type=state";
    private static final String DEPLOYMENT = "test-jmx-notifications-deployment.jar";
    private File file;

    @Override
    public void setup(ManagementClient managementClient) throws Exception {
        final File dir = new File("target/archives");
        if(dir.exists()) {
            cleanFile(dir);
        }
        dir.mkdirs();
        file = new File(dir, DEPLOYMENT);
        ServiceActivatorDeploymentUtil.createServiceActivatorListenerDeployment(file, TARGET_OBJECT_NAME, ControlledStateNotificationListener.class);
        deploy(managementClient.getControllerClient(), file);
    }

    public void setup(ModelControllerClient client, String serverGroupName) throws IOException {
        final File dir = new File("target/archives");
        if(dir.exists()) {
            cleanFile(dir);
        }
        dir.mkdirs();
        file = new File(dir, DEPLOYMENT);

        Set<Permission> additionalPermissions = new HashSet();
        if(TestSuiteEnvironment.isJ9Jvm()) {
            //fix of WFCORE-3417
            additionalPermissions.add(new FilePermission(file.getAbsolutePath()
                    .replace("archives", "domains/JmxControlledStateNotificationsTestCase/primary")
                    .replace(file.getName(), ""), "read"));
        }

        ServiceActivatorDeploymentUtil.createServiceActivatorListenerDeployment(file, TARGET_OBJECT_NAME, ControlledStateNotificationListener.class, additionalPermissions);
        deploy(client, file);
        ModelNode op = createOpNode("server-group=" + serverGroupName + "/deployment=" + file.getName(), ADD);
        op.get(ENABLED).set(true);
        RbacUtil.executeOperation(client, op, Outcome.SUCCESS);
    }

    protected void deploy(ModelControllerClient client, File file) throws IOException {
        ModelNode op = createOpNode("deployment=" + file.getName(), ADD);
        op.get(ENABLED).set(true);
        ModelNode content = op.get(CONTENT).add();
        content.get(BYTES).set(getContent(file));
        RbacUtil.executeOperation(client, op, Outcome.SUCCESS);
    }

    private byte[] getContent(File file) throws IOException {
        InputStream in = null;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            in = new FileInputStream(file);
            StreamUtils.copyStream(in, out);
            return out.toByteArray();
        } finally {
            StreamUtils.safeClose(in);
            StreamUtils.safeClose(out);
        }
    }

    protected static void removeDeployment(ModelControllerClient client, File file) throws IOException {
        ModelNode op = createOpNode("deployment=" + file.getName(), REMOVE);
        RbacUtil.executeOperation(client, op, Outcome.SUCCESS);
    }

    private static void cleanFile(File toClean) {
        if (toClean.isDirectory()) {
            for (File child : toClean.listFiles()) {
                cleanFile(child);
            }
        }
        toClean.delete();
    }

    public void tearDown(ModelControllerClient client, String serverGroupName) throws Exception {
        ModelNode op = createOpNode("server-group=" + serverGroupName + "/deployment=" + file.getName(), REMOVE);
        RbacUtil.executeOperation(client, op, Outcome.SUCCESS);
        removeDeployment(client, file);
    }

    @Override
    public void tearDown(ManagementClient managementClient) throws Exception {
        removeDeployment(managementClient.getControllerClient(), file);
    }

}
