/*
 * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation
package org.eclipse.persistence.testing.tests.junit.platform.server.wls;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.eclipse.persistence.internal.helper.JavaSEPlatform;
import org.eclipse.persistence.platform.server.ServerPlatform;
import org.eclipse.persistence.platform.server.wls.WebLogic_12_Platform;
import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;

public class WebLogic_12_PlatformTest {

    public WebLogic_12_PlatformTest() {
    }

    @After
    public void tearDown() {
        if (JavaSEPlatform.CURRENT.getMajor() < 12) {
            resetContextHelper();
        }
    }

    @Test
    public void testUsesPartitions() {
        Assume.assumeFalse("Java version is 12 above. Test will be skipped.", JavaSEPlatform.CURRENT.getMajor() >= 12);
        ServerPlatform platform = new WebLogic_12_Platform(null);
        Assert.assertFalse(platform.usesPartitions());

        setContextHelper();
        Assert.assertTrue(platform.usesPartitions());
    }

    @Test
    public void testGetPartitionId() {
        Assume.assumeFalse("Java version is 12 above. Test will be skipped.", JavaSEPlatform.CURRENT.getMajor() >= 12);
        setContextHelper();
        ServerPlatform platform = new WebLogic_12_Platform(null);
        ICtx.ctx = "test3";
        Assert.assertEquals("test3", platform.getPartitionID());
        ICtx.ctx = "test1";
        Assert.assertEquals("test1", platform.getPartitionID());
    }

    @Test
    public void testGetPartitionName() {
        Assume.assumeFalse("Java version is 12 above. Test will be skipped.", JavaSEPlatform.CURRENT.getMajor() >= 12);
        setContextHelper();
        WebLogic_12_Platform platform = new WebLogic_12_Platform(null);
        ICtx.nameCtx = "test3";
        Assert.assertEquals("test3", platform.getPartitionName());
        ICtx.nameCtx = "test1";
        Assert.assertEquals("test1", platform.getPartitionName());
    }

    @Test
    public void testIsGlobalRuntime() {
        Assume.assumeFalse("Java version is 12 above. Test will be skipped.", JavaSEPlatform.CURRENT.getMajor() >= 12);
        setContextHelper();
        WebLogic_12_Platform platform = new WebLogic_12_Platform(null);
        ICtx.isGlobal = true;
        Assert.assertTrue(platform.isGlobalRuntime());
        ICtx.isGlobal = false;
        Assert.assertFalse(platform.isGlobalRuntime());
    }

    @Test
    public void testContextHelper() {
        Assume.assumeFalse("Java version is 12 above. Test will be skipped.", JavaSEPlatform.CURRENT.getMajor() >= 12);
        Class contextHelperClass = null;
        for (Class<?> declaredClass : WebLogic_12_Platform.class.getDeclaredClasses()) {
            if ("org.eclipse.persistence.platform.server.wls.WebLogic_12_Platform$ContextHelper".equals(declaredClass.getName())) {
                contextHelperClass = declaredClass;
                break;
            }
        }
        Assert.assertNotNull("ContextHelper class not found", contextHelperClass);

        Method getCicManagerClassMethod = null;
        try {
            getCicManagerClassMethod = contextHelperClass.getDeclaredMethod("getCicManagerClass", String.class, String.class);
        } catch (NoSuchMethodException e) {
            Assert.fail("getCicManagerClass method not found: " + e.getMessage());
        }
        Assert.assertNotNull("getCicManagerClass method not found", getCicManagerClassMethod);

        getCicManagerClassMethod.setAccessible(true);
        Object result = null;
        try {
            result = getCicManagerClassMethod.invoke(contextHelperClass, "org/eclipse/persistence/testing/tests/junit/platform/server/wls/WebLogic_12_PlatformTest.class", "org.eclipse.persistence.testing.tests.junit.platform.server.wls.WebLogic_12_PlatformTest");
        } catch (Exception e) {
            Assert.fail("Failed to invoke getCicManagerClass method: " + e.getMessage());
        }
        Assert.assertNotNull("Failed to retrieve test class", result);
        try {
            result = getCicManagerClassMethod.invoke(contextHelperClass, "this/should/not/resolve", "org.eclipse.persistence.testing.tests.junit.platform.server.wls.WebLogic_12_PlatformTest");
        } catch (Exception e) {
            Assert.fail("Failed to invoke getCicManagerClass method: " + e.getMessage());
        }
        Assert.assertNull("Should have failed to retrieve test class", result);
        getCicManagerClassMethod.setAccessible(false);
    }

    private void resetContextHelper() {
        try {
            setPrivateStaticFinalField(WebLogic_12_Platform.class.getDeclaredField("ctxHelper"), null);
        } catch (NoSuchFieldException | SecurityException ex) {
            throw new RuntimeException(ex);
        }
    }

    private void setContextHelper() {
        try {
            setPrivateStaticFinalField(WebLogic_12_Platform.class.getDeclaredField("ctxHelper"), setUpCtxHelper());
        } catch (NoSuchFieldException | SecurityException ex) {
            throw new RuntimeException(ex);
        }
    }

    private Object setUpCtxHelper() {
        IMgr imgr = new IMgr();
        Constructor c = null;
        Field instanceField = null;
        Object ctxHelperInstance = null;
        try {
            Class<?> ctxHelperClass = Class.forName("org.eclipse.persistence.platform.server.wls.WebLogic_12_Platform$ContextHelper");
            c = ctxHelperClass.getDeclaredConstructors()[0];
            c.setAccessible(true);
            ctxHelperInstance = c.newInstance(imgr.getClass(), ICtx.class.getName());

            setPrivateStaticFinalField(ctxHelperClass.getDeclaredField("cicManagerClass"), IMgr.class);

            instanceField = ctxHelperClass.getDeclaredField("instance");
            instanceField.setAccessible(true);
            instanceField.set(null, ctxHelperInstance);

        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException
                | InvocationTargetException | NoSuchFieldException | SecurityException ex) {
            throw new RuntimeException(ex);
        } finally {
            if (c != null) {
                c.setAccessible(false);
            }
            if (instanceField != null) {
                instanceField.setAccessible(false);
            }
        }
        return ctxHelperInstance;
    }

    private void setPrivateStaticFinalField(Field f, Object value) {
        Field modifiersField = null;
        int orig = 0;
        try {
            f.setAccessible(true);

            // remove final modifier from field
            modifiersField = Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);
            orig = f.getModifiers();
            modifiersField.setInt(f, orig & ~Modifier.FINAL);

            f.set(null, value);
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex) {
            throw new RuntimeException(ex);
        } finally {
            if (modifiersField != null) {
                if (f != null) {
                    try {
                        modifiersField.setInt(f, orig);
                    } catch (IllegalArgumentException | IllegalAccessException ex) {
                        throw new RuntimeException(ex);
                    }
                }
                modifiersField.setAccessible(false);
            }
            if (f != null) {
                f.setAccessible(false);
            }
        }
    }

    private static final class IMgr {

        public static IMgr getInstance() {
            return new IMgr();
        }

        public ICtx getCurrentComponentInvocationContext() {
            return new ICtx();
        }
    }

    private static final class ICtx {

        static volatile String ctx;
        static volatile String nameCtx;
        static volatile boolean isGlobal;

        public ICtx() {
        }

        public String getPartitionId() {
            return ctx;
        }

        public String getPartitionName() {
            return nameCtx;
        }

        public boolean isGlobalRuntime() {
            return isGlobal;
        }

    }
}
