/*
 * 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.cassandra.db.marshal;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

import org.apache.cassandra.db.Clustering;
import org.apache.cassandra.db.ClusteringBound;
import org.apache.cassandra.db.ClusteringBoundOrBoundary;
import org.apache.cassandra.db.ClusteringBoundary;
import org.apache.cassandra.db.ClusteringPrefix;
import org.apache.cassandra.db.Digest;
import org.apache.cassandra.db.TypeSizes;
import org.apache.cassandra.db.rows.Cell;
import org.apache.cassandra.db.rows.CellPath;
import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputPlus;
import org.apache.cassandra.schema.ColumnMetadata;

import static org.apache.cassandra.db.ClusteringPrefix.Kind.*;

/**
 * ValueAccessor allows serializers and other code dealing with raw bytes to operate on different backing types
 * (ie: byte arrays, byte buffers, etc) without requiring that the supported backing types share a common type
 * ancestor and without incuring the allocation cost of a wrapper object.
 *
 * A note on byte buffers for implementors: the "value" of a byte buffer is always interpreted as beginning at
 * it's {@link ByteBuffer#position()} and having a length of {@link ByteBuffer#remaining()}. ValueAccessor
 * implementations need to maintain this internally. ValueAccessors should also never modify the state of the
 * byte buffers view (ie: offset, limit). This would also apply to value accessors for simlilar types
 * (ie: netty's ByteBuf}.
 *
 * @param <V> the backing type
 */
public interface ValueAccessor<V>
{

    /**
     * Creates db objects using the given accessors value type. ObjectFactory instances are meant to be returned
     * by the factory() method of a value accessor.
     * @param <V> the backing type
     */
    public interface ObjectFactory<V>
    {
        Cell<V> cell(ColumnMetadata column, long timestamp, int ttl, int localDeletionTime, V value, CellPath path);
        Clustering<V> clustering(V... values);
        Clustering<V> clustering();
        ClusteringBound<V> bound(ClusteringPrefix.Kind kind, V... values);
        ClusteringBound<V> bound(ClusteringPrefix.Kind kind);
        ClusteringBoundary<V> boundary(ClusteringPrefix.Kind kind, V... values);
        default ClusteringBoundOrBoundary<V> boundOrBoundary(ClusteringPrefix.Kind kind, V... values)
        {
            return kind.isBoundary() ? boundary(kind, values) : bound(kind, values);
        }

        default ClusteringBound<V> inclusiveOpen(boolean reversed, V[] boundValues)
        {
            return bound(reversed ? INCL_END_BOUND : INCL_START_BOUND, boundValues);
        }

        default ClusteringBound<V> exclusiveOpen(boolean reversed, V[] boundValues)
        {
            return bound(reversed ? EXCL_END_BOUND : EXCL_START_BOUND, boundValues);
        }

        default ClusteringBound<V> inclusiveClose(boolean reversed, V[] boundValues)
        {
            return bound(reversed ? INCL_START_BOUND : INCL_END_BOUND, boundValues);
        }

        default ClusteringBound<V> exclusiveClose(boolean reversed, V[] boundValues)
        {
            return bound(reversed ? EXCL_START_BOUND : EXCL_END_BOUND, boundValues);
        }

        default ClusteringBoundary<V> inclusiveCloseExclusiveOpen(boolean reversed, V[] boundValues)
        {
            return boundary(reversed ? EXCL_END_INCL_START_BOUNDARY : INCL_END_EXCL_START_BOUNDARY, boundValues);
        }

        default ClusteringBoundary<V> exclusiveCloseInclusiveOpen(boolean reversed, V[] boundValues)
        {
            return boundary(reversed ? INCL_END_EXCL_START_BOUNDARY : EXCL_END_INCL_START_BOUNDARY, boundValues);
        }

    }
    /**
     * @return the size of the given value
     */
    int size(V value);

    /** serializes size including a vint length prefix */
    default int sizeWithVIntLength(V value)
    {
        int size = size(value);
        return TypeSizes.sizeofUnsignedVInt(size) + size;
    }

    /** serialized size including a short length prefix */
    default int sizeWithShortLength(V value)
    {
        return 2 + size(value);
    }

    /**
     * @return true if the size of the given value is zero, false otherwise
     */
    default boolean isEmpty(V value)
    {
        return size(value) == 0;
    }

    /**
     * @return the number of bytes remaining in the value from the given offset
     */
    default int sizeFromOffset(V value, int offset)
    {
        return size(value) - offset;
    }

    /**
     * @return true if there are no bytes present after the given offset, false otherwise
     */
    default boolean isEmptyFromOffset(V value, int offset)
    {
        return sizeFromOffset(value, offset) == 0;
    }

    /**
     * allocate an instance of the accessors backing type
     * @param length size of backing typ to allocate
     */
    V[] createArray(int length);

    /**
     * Write the contents of the given value into the a DataOutputPlus
     */
    void write(V value, DataOutputPlus out) throws IOException;

    default void writeWithVIntLength(V value, DataOutputPlus out) throws IOException
    {
        out.writeUnsignedVInt(size(value));
        write(value, out);
    }

    /**
     * Write the contents of the given value into the ByteBuffer
     */
    void write(V value, ByteBuffer out);

    /**
     * copy the {@param size} bytes from the {@param src} value, starting at the offset {@param srcOffset} into
     * the {@param dst} value, starting at the offset {@param dstOffset}, using the accessor {@param dstAccessor}
     * @param <V2> the destination value type
     * @return the number of bytes copied ({@param size})
     */
    <V2> int copyTo(V src, int srcOffset, V2 dst, ValueAccessor<V2> dstAccessor, int dstOffset, int size);

    /**
     * copies a byte array into this accessors value.
     */
    int copyByteArrayTo(byte[] src, int srcOffset, V dst, int dstOffset, int size);

    /**
     * copies a byte buffer into this accessors value.
     */
    int copyByteBufferTo(ByteBuffer src, int srcOffset, V dst, int dstOffset, int size);

    /**
     * updates {@param digest} with {@param size} bytes from the contents of {@param value} starting
     * at offset {@param offset}
     */
    void digest(V value, int offset, int size, Digest digest);

    /**
     * updates {@param digest} with te contents of {@param value}
     */
    default void digest(V value, Digest digest)
    {
        digest(value, 0, size(value), digest);
    }

    /**
     * Reads a value of {@param length} bytes from {@param in}
     */
    V read(DataInputPlus in, int length) throws IOException;

    /**
     * Returns a value with the contents of {@param input} from {@param offset} to {@param length}.
     *
     * Depending on the accessor implementation, this method may:
     *  * allocate a new {@param <V>} object of {@param length}, and copy data into it
     *  * return a view of {@param input} where changes to one will be reflected in the other
     */
    V slice(V input, int offset, int length);

    /**
     * same as {@link ValueAccessor#slice(Object, int, int)}, except the length is taken from the first
     * 2 bytes from the given offset (and not included in the return value)
     */
    default V sliceWithShortLength(V input, int offset)
    {
        int size = getUnsignedShort(input, offset);
        return slice(input, offset + 2, size);
    }

    /**
     * lexicographically compare {@param left} to {@param right}
     * @param <VR> backing type of
     */
    <VR> int compare(V left, VR right, ValueAccessor<VR> accessorR);

    /**
     * compare a byte array on the left with a {@param <V>} on the right}
     */
    int compareByteArrayTo(byte[] left, V right);

    /**
     * compare a byte buffer on the left with a {@param <V>} on the right}
     */
    int compareByteBufferTo(ByteBuffer left, V right);

    default int hashCode(V value)
    {
        if (value == null)
            return 0;

        int result = 1;
        for (int i=0, isize=size(value); i<isize; i++)
            result = 31 * result + (int) getByte(value, i);

        return result;
    }

    /**
     * returns a ByteBuffer with the contents of {@param value}
     *
     * Depending on the accessor implementation, this method may:
     *  * allocate a new ByteBuffer and copy data into it
     *  * return the value, if the backing type is a bytebuffer
     */
    ByteBuffer toBuffer(V value);

    /**
     * returns a byte[] with the contents of {@param value}
     *
     * Depending on the accessor implementation, this method may:
     *  * allocate a new byte[] object and copy data into it
     *  * return the value, if the backing type is byte[]
     */
    byte[] toArray(V value);

    /**
     * returns a byte[] with {@param length} bytes copied from the contents of {@param value}
     * starting at offset {@param offset}.
     *
     * Depending on the accessor implementation, this method may:
     *  * allocate a new byte[] object and copy data into it
     *  * return the value, if the backing type is byte[], offset is 0 and {@param length} == size(value)
     */
    byte[] toArray(V value, int offset, int length);
    String toString(V value, Charset charset) throws CharacterCodingException;

    default String toString(V value) throws CharacterCodingException
    {
        return toString(value, StandardCharsets.UTF_8);
    }

    String toHex(V value);

    /** returns a boolean from offset {@param offset} */
    default boolean getBoolean(V value, int offset)
    {
        return getByte(value, offset) != 0;
    }

    /** returns a byte from offset 0 */
    byte toByte(V value);
    /** returns a byte from offset {@param offset} */
    byte getByte(V value, int offset);
    /** returns a short from offset 0 */
    short toShort(V value);
    /** returns a short from offset {@param offset} */
    short getShort(V value, int offset);
    /** returns an unsigned short from offset {@param offset} */
    int getUnsignedShort(V value, int offset);
    /** returns an int from offset 0 */
    int toInt(V value);
    /** returns an int from offset {@param offset} */
    int getInt(V value, int offset);
    /** returns a long from offset 0 */
    long toLong(V value);
    /** returns a long from offset {@param offset} */
    long getLong(V value, int offset);
    /** returns a float from offset 0 */
    float toFloat(V value);

    /** returns a double from offset 0 */
    double toDouble(V value);

    /** returns a UUID from offset 0 */
    UUID toUUID(V value);

    /**
     * writes the short value {@param value} to {@param dst} at offset {@param offset}
     * @return the number of bytes written to {@param value}
     */
    int putShort(V dst, int offset, short value);

    /**
     * writes the int value {@param value} to {@param dst} at offset {@param offset}
     * @return the number of bytes written to {@param value}
     */
    int putInt(V dst, int offset, int value);

    /**
     * writes the long value {@param value} to {@param dst} at offset {@param offset}
     * @return the number of bytes written to {@param value}
     */
    int putLong(V dst, int offset, long value);

    /** return a value with a length of 0 */
    V empty();

    /**
     * return a value containing the {@param bytes}
     *
     * Caller should assume that modifying the returned value
     * will also modify the contents of {@param bytes}
     */
    V valueOf(byte[] bytes);

    /**
     * return a value containing the {@param bytes}
     *
     * {@param src} and the returned value may share a common byte array instance, so caller should
     * assume that modifying the returned value will also modify the contents of {@param src}
     */
    V valueOf(ByteBuffer bytes);

    /** return a value containing the bytes for the given string and charset */
    V valueOf(String s, Charset charset);

    /** return a value with the bytes from {@param v}*/
    V valueOf(UUID v);
    /** return a value with the bytes from {@param v}*/
    V valueOf(boolean v);
    /** return a value with the bytes from {@param v}*/
    V valueOf(byte v);
    /** return a value with the bytes from {@param v}*/
    V valueOf(short v);
    /** return a value with the bytes from {@param v}*/
    V valueOf(int v);
    /** return a value with the bytes from {@param v}*/
    V valueOf(long v);
    /** return a value with the bytes from {@param v}*/
    V valueOf(float v);
    /** return a value with the bytes from {@param v}*/
    V valueOf(double v);

    /**
     * Convert the data in {@param src} to {@param <V>}
     *
     * {@param src} and the returned value may share a common byte array instance, so caller should
     * assume that modifying the returned value will also modify the contents of {@param src}
     */
    <V2> V convert(V2 src, ValueAccessor<V2> accessor);

    /**
     * Allocate and return a {@param <V>} instance of {@param size} bytes on the heap.
     */
    V allocate(int size);

    /**
     * returns the {@link ValueAccessor.ObjectFactory} for the backing type {@param <V>}
     */
    ObjectFactory<V> factory();

    /**
     * lexicographically compare {@param left} to {@param right}
     */
    public static <L, R> int compare(L left, ValueAccessor<L> leftAccessor, R right, ValueAccessor<R> rightAccessor)
    {
        return leftAccessor.compare(left, right, rightAccessor);
    }

    public static <L, R> boolean equals(L left, ValueAccessor<L> leftAccessor, R right, ValueAccessor<R> rightAccessor)
    {
        return compare(left, leftAccessor, right, rightAccessor) == 0;
    }
}
