/*
 * 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;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.Externalizable;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.Serializable;
import java.util.Arrays;
import org.apache.commons.io.IOUtils;
import org.apache.ignite.marshaller.Marshaller;
import org.jetbrains.annotations.Nullable;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

/**
 * IO test utilities.
 */
public final class GridTestIoUtils {
    /**
     * Serializes a given object into byte array.
     *
     * @param obj Object to serialize.
     * @return Byte array containing serialized object.
     * @throws IOException If serialization failed.
     */
    public static byte[] serializeJdk(Object obj) throws IOException {
        ByteArrayOutputStream byteOut = null;

        ObjectOutputStream objOut = null;

        try {
            // Allocate half of kilobyte to avoid very small resizings.
            byteOut = new ByteArrayOutputStream(512);

            objOut = new ObjectOutputStream(byteOut);

            // Make sure that we serialize only task, without
            // class loader.
            objOut.writeObject(obj);

            objOut.flush();

            return byteOut.toByteArray();
        }
        finally {
            close(objOut);
            close(byteOut);
        }
    }

    /**
     * Deserializes passed in bytes using provided class loader.
     *
     * @param <T> Type of result object.
     * @param bytes Object bytes to deserialize.
     * @return Deserialized object.
     * @throws IOException If deserialization failed.
     * @throws ClassNotFoundException If deserialization failed.
     */
    public static <T extends Serializable> T deserializeJdk(byte[] bytes) throws IOException, ClassNotFoundException {
        ObjectInputStream in = null;

        try {
            in = new ObjectInputStream(new ByteArrayInputStream(bytes));

            return (T)in.readObject();
        }
        finally {
            close(in);
        }
    }

    /**
     * Deserializes passed in bytes using provided class loader.
     *
     * @param <T> Type of result object.
     * @param bytes Object bytes to deserialize.
     * @param clsLdr Class loader.
     * @return Deserialized object.
     * @throws IOException If deserialization failed.
     * @throws ClassNotFoundException If deserialization failed.
     */
    public static <T> T deserializeJdk(byte[] bytes, final ClassLoader clsLdr)
        throws IOException, ClassNotFoundException {
        ObjectInputStream in = null;

        try {
            in = new ObjectInputStream(new ByteArrayInputStream(bytes)) {
                @Override protected Class<?> resolveClass(ObjectStreamClass desc) throws ClassNotFoundException {
                    return clsLdr.loadClass(desc.getName());
                }
            };

            return (T)in.readObject();
        }
        finally {
            close(in);
        }
    }

    /**
     * @param <T> Type of result object.
     * @param obj Object to marshal/unmarshal.
     * @param marshaller Marshaller to use for serialization.
     * @return The same object, but passed through marshaller: obj->marshal->buf->unmarshal->copy.
     * @throws Exception If failed.
     */
    public static <T> T externalize(Externalizable obj, Marshaller marshaller) throws Exception {
        assert marshaller != null;

        byte[] buf = marshaller.marshal(obj);

        // Sleep to make sure that clock advances (necessary for some tests)
        Thread.sleep(10);

        return (T)marshaller.unmarshal(buf, obj.getClass().getClassLoader());
    }

    /**
     * Validate streams generate the same output.
     *
     * @param expIn Expected input stream.
     * @param actIn Actual input stream.
     * @param expSize Expected size of the streams.
     * @throws IOException In case of any IO exception.
     */
    public static void assertEqualStreams(InputStream expIn, InputStream actIn,
        @Nullable Long expSize) throws IOException {
        int bufSize = 2345;
        byte buf1[] = new byte[bufSize];
        byte buf2[] = new byte[bufSize];
        long pos = 0;

        while (true) {
            int i1 = actIn.read(buf1, 0, bufSize);

            int i2;

            if (i1 == -1) // Expects EOF?
                i2 = expIn.read(buf2, 0, 1); // Try to read at least 1 byte guaranted by stream's API.
            else
                IOUtils.readFully(expIn, buf2, 0, i2 = i1); // Read the same bytes count as from actual stream.

            if (i1 != i2)
                fail("Expects the same data [pos=" + pos + ", i1=" + i1 + ", i2=" + i2 + ']');

            if (i1 == -1)
                break; // EOF

            // i1 == bufSize => compare buffers.
            // i1 <  bufSize => Compare part of buffers, rest of buffers are equal from previous iteration.
            assertTrue("Expects the same data [pos=" + pos + ", i1=" + i1 + ", i2=" + i2 + ']',
                Arrays.equals(buf1, buf2));

            pos += i1;
        }

        if (expSize != null)
            assertEquals(expSize.longValue(), pos);
    }

    /**
     * Gets short value from byte array assuming that value stored in little-endian byte order.
     *
     * @param arr Byte array.
     */
    public static short getShortByByteLE(byte[] arr) {
        return getShortByByteLE(arr, 0);
    }

    /**
     * Gets short value from byte array assuming that value stored in little-endian byte order.
     *
     * @param arr Byte array.
     * @param off Offset.
     */
    public static short getShortByByteLE(byte[] arr, int off) {
        return (short)((arr[off] & 0xff) | arr[off + 1] << 8);
    }

    /**
     * Gets char value from byte array assuming that value stored in little-endian byte order.
     *
     * @param arr Byte array.
     */
    public static char getCharByByteLE(byte[] arr) {
        return getCharByByteLE(arr, 0);
    }

    /**
     * Gets char value from byte array assuming that value stored in little-endian byte order.
     *
     * @param arr Byte array.
     * @param off Offset.
     */
    public static char getCharByByteLE(byte[] arr, int off) {
        return (char)((arr[off] & 0xff) | arr[off + 1] << 8);
    }

    /**
     * Gets integer value from byte array assuming that value stored in little-endian byte order.
     *
     * @param arr Byte array.
     */
    public static int getIntByByteLE(byte[] arr) {
        return getIntByByteLE(arr, 0);
    }

    /**
     * Gets integer value from byte array assuming that value stored in little-endian byte order.
     *
     * @param arr Byte array.
     * @param off Offset.
     */
    public static int getIntByByteLE(byte[] arr, int off) {
        return ((int)arr[off] & 0xff) | ((int)arr[off + 1] & 0xff) << 8 |
            ((int)arr[off + 2] & 0xff) << 16 | ((int)arr[off + 3] & 0xff) << 24;
    }

    /**
     * Gets long value from byte array assuming that value stored in little-endian byte order.
     *
     * @param arr Byte array.
     */
    public static long getLongByByteLE(byte[] arr) {
        return getLongByByteLE(arr, 0);
    }

    /**
     * Gets long value from byte array assuming that value stored in little-endian byte order.
     *
     * @param arr Byte array.
     * @param off Offset.
     */
    public static long getLongByByteLE(byte[] arr, int off) {
        return ((long)arr[off] & 0xff) | ((long)arr[off + 1] & 0xff) << 8 | ((long)arr[off + 2] & 0xff) << 16 |
            ((long)arr[off + 3] & 0xff) << 24 | ((long)arr[off + 4] & 0xff) << 32 | ((long)arr[off + 5] & 0xff) << 40 |
            ((long)arr[off + 6] & 0xff) << 48 | ((long)arr[off + 7] & 0xff) << 56;
    }

    /**
     * Gets float value from byte array assuming that value stored in little-endian byte order.
     *
     * @param arr Byte array.
     */
    public static float getFloatByByteLE(byte[] arr) {
        return getFloatByByteLE(arr, 0);
    }

    /**
     * Gets float value from byte array assuming that value stored in little-endian byte order.
     *
     * @param arr Byte array.
     * @param off Offset.
     */
    public static float getFloatByByteLE(byte[] arr, int off) {
        return Float.intBitsToFloat(getIntByByteLE(arr, off));
    }

    /**
     * Gets double value from byte array assuming that value stored in little-endian byte order.
     *
     * @param arr Byte array.
     */
    public static double getDoubleByByteLE(byte[] arr) {
        return getDoubleByByteLE(arr, 0);
    }

    /**
     * Gets double value from byte array assuming that value stored in little-endian byte order.
     *
     * @param arr Byte array.
     * @param off Offset.
     */
    public static double getDoubleByByteLE(byte[] arr, int off) {
        return Double.longBitsToDouble(getLongByByteLE(arr, off));
    }

    /**
     * Closes resource.
     *
     * @param c Resource
     * @throws IOException If failed to close resource.
     */
    private static void close(Closeable c) throws IOException {
        if (c != null)
            c.close();
    }

    /**
     * Ensure singleton.
     */
    private GridTestIoUtils() {
        // No-op.
    }
}
