/*
 * 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.internal.binary;

import org.apache.ignite.IgniteIllegalStateException;
import org.apache.ignite.internal.IgniteKernal;
import org.apache.ignite.internal.IgnitionEx;
import org.apache.ignite.internal.binary.streams.BinaryHeapInputStream;
import org.apache.ignite.internal.binary.streams.BinaryInputStream;
import org.apache.ignite.internal.binary.streams.BinaryOutputStream;
import org.apache.ignite.binary.BinaryObjectException;
import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
import org.apache.ignite.internal.processors.cacheobject.IgniteCacheObjectProcessor;
import org.jetbrains.annotations.Nullable;

/**
 * Binary objects marshaller.
 */
public class GridBinaryMarshaller {
    /** */
    public static final ThreadLocal<Boolean> KEEP_BINARIES = new ThreadLocal<Boolean>() {
        @Override protected Boolean initialValue() {
            return true;
        }
    };

    /** Binary context in TLS store. */
    private static final ThreadLocal<BinaryContext> BINARY_CTX = new ThreadLocal<>();

    /** */
    public static final byte OPTM_MARSH = -2;

    /** */
    public static final byte BYTE = 1;

    /** */
    public static final byte SHORT = 2;

    /** */
    public static final byte INT = 3;

    /** */
    public static final byte LONG = 4;

    /** */
    public static final byte FLOAT = 5;

    /** */
    public static final byte DOUBLE = 6;

    /** */
    public static final byte CHAR = 7;

    /** */
    public static final byte BOOLEAN = 8;

    /** */
    public static final byte DECIMAL = 30;

    /** */
    public static final byte STRING = 9;

    /** */
    public static final byte UUID = 10;

    /** */
    public static final byte DATE = 11;

    /** */
    public static final byte BYTE_ARR = 12;

    /** */
    public static final byte SHORT_ARR = 13;

    /** */
    public static final byte INT_ARR = 14;

    /** */
    public static final byte LONG_ARR = 15;

    /** */
    public static final byte FLOAT_ARR = 16;

    /** */
    public static final byte DOUBLE_ARR = 17;

    /** */
    public static final byte CHAR_ARR = 18;

    /** */
    public static final byte BOOLEAN_ARR = 19;

    /** */
    public static final byte DECIMAL_ARR = 31;

    /** */
    public static final byte STRING_ARR = 20;

    /** */
    public static final byte UUID_ARR = 21;

    /** */
    public static final byte DATE_ARR = 22;

    /** */
    public static final byte OBJ_ARR = 23;

    /** */
    public static final byte COL = 24;

    /** */
    public static final byte MAP = 25;

    /** */
    public static final byte BINARY_OBJ = 27;

    /** */
    public static final byte ENUM = 28;

    /** */
    public static final byte ENUM_ARR = 29;

    /** */
    public static final byte CLASS = 32;

    /** Timestamp. */
    public static final byte TIMESTAMP = 33;

    /** Timestamp array. */
    public static final byte TIMESTAMP_ARR = 34;

    /** Proxy. */
    public static final byte PROXY = 35;

    /** Time. */
    public static final byte TIME = 36;

    /** Time array. */
    public static final byte TIME_ARR = 37;

    /** Binary enum */
    public static final byte BINARY_ENUM = 38;

    /** */
    public static final byte NULL = (byte)101;

    /** */
    public static final byte HANDLE = (byte)102;

    /** */
    public static final byte OBJ = (byte)103;

    /** */
    public static final byte USER_SET = -1;

    /** */
    public static final byte USER_COL = 0;

    /** */
    public static final byte ARR_LIST = 1;

    /** */
    public static final byte LINKED_LIST = 2;

    /** */
    public static final byte HASH_SET = 3;

    /** */
    public static final byte LINKED_HASH_SET = 4;

    /** */
    public static final byte SINGLETON_LIST = 5;

    /** */
    public static final byte HASH_MAP = 1;

    /** */
    public static final byte LINKED_HASH_MAP = 2;

    /** */
    public static final byte PLATFORM_JAVA_OBJECT_FACTORY_PROXY = 99;

    /** */
    public static final int OBJECT = -1;

    /** */
    public static final int UNREGISTERED_TYPE_ID = 0;

    /** Protocol version. */
    public static final byte PROTO_VER = 1;

    /** Protocol version position. */
    public static final int PROTO_VER_POS = 1;

    /** Flags position in header. */
    public static final int FLAGS_POS = 2;

    /** */
    public static final int TYPE_ID_POS = 4;

    /** */
    public static final int HASH_CODE_POS = 8;

    /** */
    public static final int TOTAL_LEN_POS = 12;

    /** */
    public static final int SCHEMA_ID_POS = 16;

    /** Schema or raw offset position. */
    public static final int SCHEMA_OR_RAW_OFF_POS = 20;

    /** */
    public static final byte DFLT_HDR_LEN = 24;

    /** */
    private final BinaryContext ctx;

    /**
     * @param ctx Context.
     */
    public GridBinaryMarshaller(BinaryContext ctx) {
        this.ctx = ctx;
    }

    /**
     * @param obj Object to marshal.
     * @param failIfUnregistered Throw exception if class isn't registered.
     * @return Byte array.
     * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
     */
    public byte[] marshal(@Nullable Object obj, boolean failIfUnregistered) throws BinaryObjectException {
        if (obj == null)
            return new byte[] { NULL };

        try (BinaryWriterExImpl writer = new BinaryWriterExImpl(ctx)) {
            writer.failIfUnregistered(failIfUnregistered);

            writer.marshal(obj);

            return writer.array();
        }
    }

    /**
     * @param bytes Bytes array.
     * @return Binary object.
     * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
     */
    @SuppressWarnings("unchecked")
    @Nullable public <T> T unmarshal(byte[] bytes, @Nullable ClassLoader clsLdr) throws BinaryObjectException {
        assert bytes != null;

        BinaryContext oldCtx = pushContext(ctx);

        try {
            return (T) BinaryUtils.unmarshal(BinaryHeapInputStream.create(bytes, 0), ctx, clsLdr);
        }
        finally {
            popContext(oldCtx);
        }
    }

    /**
     * @param in Input stream.
     * @return Binary object.
     * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
     */
    @SuppressWarnings("unchecked")
    @Nullable public <T> T unmarshal(BinaryInputStream in) throws BinaryObjectException {
        BinaryContext oldCtx = pushContext(ctx);

        try {
            return (T)BinaryUtils.unmarshal(in, ctx, null);
        }
        finally {
            popContext(oldCtx);
        }
    }

    /**
     * @param arr Byte array.
     * @param ldr Class loader.
     * @return Deserialized object.
     * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
     */
    @SuppressWarnings("unchecked")
    @Nullable public <T> T deserialize(byte[] arr, @Nullable ClassLoader ldr) throws BinaryObjectException {
        assert arr != null;
        assert arr.length > 0;

        if (arr[0] == NULL)
            return null;

        BinaryContext oldCtx = pushContext(ctx);

        try {
            return (T)new BinaryReaderExImpl(ctx, BinaryHeapInputStream.create(arr, 0), ldr, true).deserialize();
        }
        finally {
            popContext(oldCtx);
        }
    }

    /**
     * Push binary context and return the old one.
     *
     * @return Old binary context.
     */
    public BinaryContext pushContext() {
        return pushContext(ctx);
    }

    /**
     * Push binary context and return the old one.
     *
     * @param ctx Binary context.
     * @return Old binary context.
     */
    @Nullable private static BinaryContext pushContext(BinaryContext ctx) {
        BinaryContext old = BINARY_CTX.get();

        BINARY_CTX.set(ctx);

        return old;
    }

    /**
     * Pop binary context and restore the old one.
     *
     * @param oldCtx Old binary context.
     */
    public static void popContext(@Nullable BinaryContext oldCtx) {
        BINARY_CTX.set(oldCtx);
    }

    /**
     * Creates a reader.
     *
     * @param stream Stream.
     * @return Reader.
     */
    public BinaryReaderExImpl reader(BinaryInputStream stream) {
        assert stream != null;

        return new BinaryReaderExImpl(ctx, stream, null, true);
    }

    /**
     * Whether object must be deserialized anyway. I.e. it cannot be converted to BinaryObject.
     *
     * @param obj Object.
     * @return {@code True} if object will be deserialized on unmarshal.
     */
    public boolean mustDeserialize(Object obj) {
        return obj != null && ctx.mustDeserialize(obj.getClass());
    }

    /**
     * Gets writer for the given output stream.
     *
     * @param out Output stream.
     * @return Writer.
     */
    public BinaryWriterExImpl writer(BinaryOutputStream out) {
        return new BinaryWriterExImpl(ctx, out, BinaryThreadLocalContext.get().schemaHolder(), null);
    }

    /**
     * @return Context.
     */
    public BinaryContext context() {
        return ctx;
    }

    /**
     * @return Thread-bound context.
     */
    public static BinaryContext threadLocalContext() {
        BinaryContext ctx = GridBinaryMarshaller.BINARY_CTX.get();

        if (ctx == null) {
            IgniteKernal ignite = IgnitionEx.localIgnite();

            IgniteCacheObjectProcessor proc = ignite.context().cacheObjects();

            if (proc instanceof CacheObjectBinaryProcessorImpl)
                return ((CacheObjectBinaryProcessorImpl)proc).binaryContext();
            else
                throw new IgniteIllegalStateException("Ignite instance must be started with " +
                    BinaryMarshaller.class.getName() + " [name=" + ignite.name() + ']');
        }

        return ctx;
    }
}
