/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.ignite.marshaller;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.apache.ignite.Ignite;
import org.apache.ignite.configuration.DataStorageConfiguration;
import org.apache.ignite.internal.IgniteKernal;
import org.apache.ignite.internal.MarshallerContextImpl;
import org.apache.ignite.internal.processors.closure.GridClosureProcessor;
import org.apache.ignite.internal.processors.marshaller.MappedName;
import org.apache.ignite.internal.processors.marshaller.MarshallerMappingItem;
import org.apache.ignite.internal.processors.pool.PoolProcessor;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.testframework.junits.GridTestKernalContext;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.junit.Test;

import static java.nio.file.Files.readAllBytes;
import static org.apache.ignite.internal.MarshallerPlatformIds.JAVA_ID;

/**
 * Test marshaller context.
 */
public class MarshallerContextSelfTest extends GridCommonAbstractTest {
    /** */
    private GridTestKernalContext ctx;

    /** */
    private ExecutorService execSvc;

    /** {@inheritDoc} */
    @Override protected void beforeTest() throws Exception {
        ctx = newContext();
        execSvc = Executors.newSingleThreadExecutor();

        ctx.add(new PoolProcessor(ctx) {
            @Override public ExecutorService getSystemExecutorService() {
                return execSvc;
            }
        });

        ctx.add(new GridClosureProcessor(ctx));
    }

    /** {@inheritDoc} */
    @Override protected void afterTest() throws Exception {
        stopAllGrids();
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testClassName() throws Exception {
        MarshallerContextImpl marshCtx = new MarshallerContextImpl(null, null);

        marshCtx.onMarshallerProcessorStarted(ctx, null);

        MarshallerMappingItem item = new MarshallerMappingItem(JAVA_ID, 1, String.class.getName());

        marshCtx.onMappingProposed(item);

        marshCtx.onMappingAccepted(item);

        try (Ignite g1 = startGrid(1)) {
            marshCtx = ((IgniteKernal)g1).context().marshallerContext();
            String clsName = marshCtx.getClassName(JAVA_ID, 1);

            assertEquals("java.lang.String", clsName);
        }
    }

    /**
     * Test for adding non-java mappings (with platformId &gt; 0) to MarshallerContext and collecting them
     * for discovery.
     *
     * @throws Exception If failed.
     */
    @Test
    public void testMultiplatformMappingsCollecting() throws Exception {
        String nonJavaClassName = "random.platform.Mapping";

        MarshallerContextImpl marshCtx = new MarshallerContextImpl(null, null);

        marshCtx.onMarshallerProcessorStarted(ctx, null);

        MarshallerMappingItem item = new MarshallerMappingItem((byte)2, 101, nonJavaClassName);

        marshCtx.onMappingProposed(item);

        marshCtx.onMappingAccepted(item);

        ArrayList<Map<Integer, MappedName>> allMappings = marshCtx.getCachedMappings();

        assertEquals(allMappings.size(), 3);

        assertTrue(allMappings.get(0).isEmpty());

        assertTrue(allMappings.get(1).isEmpty());

        Map<Integer, MappedName> nonJavaMappings = allMappings.get(2);

        assertNotNull(nonJavaMappings);

        assertNotNull(nonJavaMappings.get(101));

        assertEquals(nonJavaClassName, nonJavaMappings.get(101).className());
    }

    /**
     * Test for adding non-java mappings (with platformId &gt; 0) to MarshallerContext and distributing them
     * to newly joining nodes.
     *
     * @throws Exception If failed.
     */
    @Test
    public void testMultiplatformMappingsDistributing() throws Exception {
        String nonJavaClassName = "random.platform.Mapping";

        Ignite grid0 = startGrid(0);

        MarshallerContextImpl marshCtx0 = ((IgniteKernal)grid0).context().marshallerContext();

        MarshallerMappingItem item = new MarshallerMappingItem((byte)2, 101, nonJavaClassName);

        marshCtx0.onMappingProposed(item);

        marshCtx0.onMappingAccepted(item);

        Ignite grid1 = startGrid(1);

        MarshallerContextImpl marshCtx1 = ((IgniteKernal)grid1).context().marshallerContext();

        assertEquals(nonJavaClassName, marshCtx1.getClassName((byte)2, 101));
    }

    /**
     * @throws Exception If failed.
     */
    @Test
    public void testOnUpdated() throws Exception {
        File workDir = U.resolveWorkDirectory(U.defaultWorkDirectory(), DataStorageConfiguration.DFLT_MARSHALLER_PATH, false);
        MarshallerContextImpl ctx = new MarshallerContextImpl(null, null);

        ctx.onMarshallerProcessorStarted(this.ctx, null);

        MarshallerMappingItem item1 = new MarshallerMappingItem(JAVA_ID, 1, String.class.getName());

        ctx.onMappingAccepted(item1);

        // Wait until marshaller context write class to file.
        U.sleep(2_000);

        checkFileName("java.lang.String", Paths.get(workDir + "/1.classname0"));

        MarshallerMappingItem item2 = new MarshallerMappingItem((byte)2, 2, "Random.Class.Name");

        ctx.onMappingProposed(item2);
        ctx.onMappingAccepted(item2);

        execSvc.shutdown();

        if (execSvc.awaitTermination(1000, TimeUnit.MILLISECONDS))
            checkFileName("Random.Class.Name", Paths.get(workDir + "/2.classname2"));
        else
            fail("Failed to wait for executor service to shutdown");
    }

    /**
     * Tests that there is a null value inserted in allCaches list
     * if platform ids passed to marshaller cache were not sequential (like 0, 2).
     */
    @Test
    public void testCacheStructure0() throws Exception {
        MarshallerContextImpl ctx = new MarshallerContextImpl(null, null);

        ctx.onMarshallerProcessorStarted(this.ctx, null);

        MarshallerMappingItem item1 = new MarshallerMappingItem(JAVA_ID, 1, String.class.getName());

        ctx.onMappingAccepted(item1);

        MarshallerMappingItem item2 = new MarshallerMappingItem((byte)2, 2, "Random.Class.Name");

        ctx.onMappingProposed(item2);

        List list = U.field(ctx, "allCaches");

        assertNotNull("Mapping cache is null for platformId: 0", list.get(0));
        assertNull("Mapping cache is not null for platformId: 1", list.get(1));
        assertNotNull("Mapping cache is null for platformId: 2", list.get(2));

        boolean excObserved = false;
        try {
            list.get(3);
        }
        catch (ArrayIndexOutOfBoundsException ignored) {
            excObserved = true;
        }
        assertTrue("ArrayIndexOutOfBoundsException had to be thrown", excObserved);
    }

    /**
     * Tests that there are no null values in allCaches list
     * if platform ids passed to marshaller context were sequential.
     */
    @Test
    public void testCacheStructure1() throws Exception {
        MarshallerContextImpl ctx = new MarshallerContextImpl(null, null);

        ctx.onMarshallerProcessorStarted(this.ctx, null);

        MarshallerMappingItem item1 = new MarshallerMappingItem(JAVA_ID, 1, String.class.getName());

        ctx.onMappingAccepted(item1);

        MarshallerMappingItem item2 = new MarshallerMappingItem((byte)1, 2, "Random.Class.Name");

        ctx.onMappingProposed(item2);

        List list = U.field(ctx, "allCaches");

        assertNotNull("Mapping cache is null for platformId: 0", list.get(0));
        assertNotNull("Mapping cache is null for platformId: 1", list.get(1));

        boolean excObserved = false;

        try {
            list.get(2);
        }
        catch (ArrayIndexOutOfBoundsException ignored) {
            excObserved = true;
        }

        assertTrue("ArrayIndexOutOfBoundsException had to be thrown", excObserved);
    }

    /**
     * @param expected Expected.
     * @param pathToReal Path to real.
     */
    private void checkFileName(String expected, Path pathToReal) throws IOException {
        byte[] fileContent = readAllBytes(pathToReal);

        assert fileContent != null && fileContent.length > 0;

        assertEquals(expected, new String(fileContent));
    }
}
