/*
 * 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.cql3.functions;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.List;

import com.google.common.reflect.TypeToken;

import com.datastax.driver.core.CodecRegistry;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.TypeCodec;
import com.datastax.driver.core.exceptions.InvalidTypeException;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.transport.ProtocolVersion;

/**
 * Helper class for User Defined Functions, Types and Aggregates.
 */
public final class UDHelper
{
    // TODO make these c'tors and methods public in Java-Driver - see https://datastax-oss.atlassian.net/browse/JAVA-502
    private static final MethodHandle methodParseOne;
    private static final CodecRegistry codecRegistry;
    static
    {
        try
        {
            Class<?> cls = Class.forName("com.datastax.driver.core.DataTypeClassNameParser");
            Method m = cls.getDeclaredMethod("parseOne", String.class, com.datastax.driver.core.ProtocolVersion.class, CodecRegistry.class);
            m.setAccessible(true);
            methodParseOne = MethodHandles.lookup().unreflect(m);
            codecRegistry = new CodecRegistry();
        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }
    }

    static TypeCodec<Object>[] codecsFor(DataType[] dataType)
    {
        TypeCodec<Object>[] codecs = new TypeCodec[dataType.length];
        for (int i = 0; i < dataType.length; i++)
            codecs[i] = codecFor(dataType[i]);
        return codecs;
    }

    public static TypeCodec<Object> codecFor(DataType dataType)
    {
        return codecRegistry.codecFor(dataType);
    }

    /**
     * Construct an array containing the Java classes for the given Java Driver {@link com.datastax.driver.core.DataType}s.
     *
     * @param dataTypes  array with UDF argument types
     * @param calledOnNullInput whether to allow {@code null} as an argument value
     * @return array of same size with UDF arguments
     */
    public static TypeToken<?>[] typeTokens(TypeCodec<Object>[] dataTypes, boolean calledOnNullInput)
    {
        TypeToken<?>[] paramTypes = new TypeToken[dataTypes.length];
        for (int i = 0; i < paramTypes.length; i++)
        {
            TypeToken<?> typeToken = dataTypes[i].getJavaType();
            if (!calledOnNullInput)
            {
                // only care about classes that can be used in a data type
                Class<?> clazz = typeToken.getRawType();
                if (clazz == Integer.class)
                    typeToken = TypeToken.of(int.class);
                else if (clazz == Long.class)
                    typeToken = TypeToken.of(long.class);
                else if (clazz == Byte.class)
                    typeToken = TypeToken.of(byte.class);
                else if (clazz == Short.class)
                    typeToken = TypeToken.of(short.class);
                else if (clazz == Float.class)
                    typeToken = TypeToken.of(float.class);
                else if (clazz == Double.class)
                    typeToken = TypeToken.of(double.class);
                else if (clazz == Boolean.class)
                    typeToken = TypeToken.of(boolean.class);
            }
            paramTypes[i] = typeToken;
        }
        return paramTypes;
    }

    /**
     * Construct an array containing the Java Driver {@link com.datastax.driver.core.DataType}s for the
     * C* internal types.
     *
     * @param abstractTypes list with UDF argument types
     * @return array with argument types as {@link com.datastax.driver.core.DataType}
     */
    public static DataType[] driverTypes(List<AbstractType<?>> abstractTypes)
    {
        DataType[] argDataTypes = new DataType[abstractTypes.size()];
        for (int i = 0; i < argDataTypes.length; i++)
            argDataTypes[i] = driverType(abstractTypes.get(i));
        return argDataTypes;
    }

    /**
     * Returns the Java Driver {@link com.datastax.driver.core.DataType} for the C* internal type.
     */
    public static DataType driverType(AbstractType abstractType)
    {
        CQL3Type cqlType = abstractType.asCQL3Type();
        String abstractTypeDef = cqlType.getType().toString();
        return driverTypeFromAbstractType(abstractTypeDef);
    }

    public static DataType driverTypeFromAbstractType(String abstractTypeDef)
    {
        try
        {
            return (DataType) methodParseOne.invoke(abstractTypeDef,
                                                    com.datastax.driver.core.ProtocolVersion.fromInt(ProtocolVersion.CURRENT.asInt()),
                                                    codecRegistry);
        }
        catch (RuntimeException | Error e)
        {
            // immediately rethrow these...
            throw e;
        }
        catch (Throwable e)
        {
            throw new RuntimeException("cannot parse driver type " + abstractTypeDef, e);
        }
    }

    public static Object deserialize(TypeCodec<?> codec, ProtocolVersion protocolVersion, ByteBuffer value)
    {
        return codec.deserialize(value, com.datastax.driver.core.ProtocolVersion.fromInt(protocolVersion.asInt()));
    }

    public static ByteBuffer serialize(TypeCodec<?> codec, ProtocolVersion protocolVersion, Object value)
    {
        if (!codec.getJavaType().getRawType().isAssignableFrom(value.getClass()))
            throw new InvalidTypeException("Invalid value for CQL type " + codec.getCqlType().getName().toString());

        return ((TypeCodec)codec).serialize(value, com.datastax.driver.core.ProtocolVersion.fromInt(protocolVersion.asInt()));
    }

    public static Class<?> asJavaClass(TypeCodec<?> codec)
    {
        return codec.getJavaType().getRawType();
    }

    public static boolean isNullOrEmpty(AbstractType<?> type, ByteBuffer bb)
    {
        return bb == null ||
               (bb.remaining() == 0 && type.isEmptyValueMeaningless());
    }
}
