/*
 * 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.transport.messages;

import java.net.InetAddress;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.CodecException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.cassandra.cql3.functions.FunctionName;
import org.apache.cassandra.db.ConsistencyLevel;
import org.apache.cassandra.db.WriteType;
import org.apache.cassandra.exceptions.*;
import org.apache.cassandra.transport.*;
import org.apache.cassandra.utils.MD5Digest;

/**
 * Message to indicate an error to the client.
 */
public class ErrorMessage extends Message.Response
{
    private static final Logger logger = LoggerFactory.getLogger(ErrorMessage.class);

    public static final Message.Codec<ErrorMessage> codec = new Message.Codec<ErrorMessage>()
    {
        public ErrorMessage decode(ByteBuf body, ProtocolVersion version)
        {
            ExceptionCode code = ExceptionCode.fromValue(body.readInt());
            String msg = CBUtil.readString(body);

            TransportException te = null;
            switch (code)
            {
                case SERVER_ERROR:
                    te = new ServerError(msg);
                    break;
                case PROTOCOL_ERROR:
                    te = new ProtocolException(msg);
                    break;
                case BAD_CREDENTIALS:
                    te = new AuthenticationException(msg);
                    break;
                case UNAVAILABLE:
                    {
                        ConsistencyLevel cl = CBUtil.readConsistencyLevel(body);
                        int required = body.readInt();
                        int alive = body.readInt();
                        te = new UnavailableException(cl, required, alive);
                    }
                    break;
                case OVERLOADED:
                    te = new OverloadedException(msg);
                    break;
                case IS_BOOTSTRAPPING:
                    te = new IsBootstrappingException();
                    break;
                case TRUNCATE_ERROR:
                    te = new TruncateException(msg);
                    break;
                case WRITE_FAILURE:
                case READ_FAILURE:
                    {
                        ConsistencyLevel cl = CBUtil.readConsistencyLevel(body);
                        int received = body.readInt();
                        int blockFor = body.readInt();
                        // The number of failures is also present in protocol v5, but used instead to specify the size of the failure map
                        int failure = body.readInt();

                        Map<InetAddress, RequestFailureReason> failureReasonByEndpoint = new ConcurrentHashMap<>();
                        if (version.isGreaterOrEqualTo(ProtocolVersion.V5))
                        {
                            for (int i = 0; i < failure; i++)
                            {
                                InetAddress endpoint = CBUtil.readInetAddr(body);
                                RequestFailureReason failureReason = RequestFailureReason.fromCode(body.readUnsignedShort());
                                failureReasonByEndpoint.put(endpoint, failureReason);
                            }
                        }

                        if (code == ExceptionCode.WRITE_FAILURE)
                        {
                            WriteType writeType = Enum.valueOf(WriteType.class, CBUtil.readString(body));
                            te = new WriteFailureException(cl, received, blockFor, writeType, failureReasonByEndpoint);
                        }
                        else
                        {
                            byte dataPresent = body.readByte();
                            te = new ReadFailureException(cl, received, blockFor, dataPresent != 0, failureReasonByEndpoint);
                        }
                    }
                    break;
                case WRITE_TIMEOUT:
                case READ_TIMEOUT:
                    ConsistencyLevel cl = CBUtil.readConsistencyLevel(body);
                    int received = body.readInt();
                    int blockFor = body.readInt();
                    if (code == ExceptionCode.WRITE_TIMEOUT)
                    {
                        WriteType writeType = Enum.valueOf(WriteType.class, CBUtil.readString(body));
                        te = new WriteTimeoutException(writeType, cl, received, blockFor);
                    }
                    else
                    {
                        byte dataPresent = body.readByte();
                        te = new ReadTimeoutException(cl, received, blockFor, dataPresent != 0);
                    }
                    break;
                case FUNCTION_FAILURE:
                    String fKeyspace = CBUtil.readString(body);
                    String fName = CBUtil.readString(body);
                    List<String> argTypes = CBUtil.readStringList(body);
                    te = new FunctionExecutionException(new FunctionName(fKeyspace, fName), argTypes, msg);
                    break;
                case UNPREPARED:
                    {
                        MD5Digest id = MD5Digest.wrap(CBUtil.readBytes(body));
                        te = new PreparedQueryNotFoundException(id);
                    }
                    break;
                case SYNTAX_ERROR:
                    te = new SyntaxException(msg);
                    break;
                case UNAUTHORIZED:
                    te = new UnauthorizedException(msg);
                    break;
                case INVALID:
                    te = new InvalidRequestException(msg);
                    break;
                case CONFIG_ERROR:
                    te = new ConfigurationException(msg);
                    break;
                case ALREADY_EXISTS:
                    String ksName = CBUtil.readString(body);
                    String cfName = CBUtil.readString(body);
                    if (cfName.isEmpty())
                        te = new AlreadyExistsException(ksName);
                    else
                        te = new AlreadyExistsException(ksName, cfName);
                    break;
            }
            return new ErrorMessage(te);
        }

        public void encode(ErrorMessage msg, ByteBuf dest, ProtocolVersion version)
        {
            final TransportException err = getBackwardsCompatibleException(msg, version);
            dest.writeInt(err.code().value);
            String errorString = err.getMessage() == null ? "" : err.getMessage();
            CBUtil.writeString(errorString, dest);

            switch (err.code())
            {
                case UNAVAILABLE:
                    UnavailableException ue = (UnavailableException)err;
                    CBUtil.writeConsistencyLevel(ue.consistency, dest);
                    dest.writeInt(ue.required);
                    dest.writeInt(ue.alive);
                    break;
                case WRITE_FAILURE:
                case READ_FAILURE:
                    {
                        RequestFailureException rfe = (RequestFailureException)err;
                        boolean isWrite = err.code() == ExceptionCode.WRITE_FAILURE;

                        CBUtil.writeConsistencyLevel(rfe.consistency, dest);
                        dest.writeInt(rfe.received);
                        dest.writeInt(rfe.blockFor);
                        // The number of failures is also present in protocol v5, but used instead to specify the size of the failure map
                        dest.writeInt(rfe.failureReasonByEndpoint.size());

                        if (version.isGreaterOrEqualTo(ProtocolVersion.V5))
                        {
                            for (Map.Entry<InetAddress, RequestFailureReason> entry : rfe.failureReasonByEndpoint.entrySet())
                            {
                                CBUtil.writeInetAddr(entry.getKey(), dest);
                                dest.writeShort(entry.getValue().code);
                            }
                        }

                        if (isWrite)
                            CBUtil.writeString(((WriteFailureException)rfe).writeType.toString(), dest);
                        else
                            dest.writeByte((byte)(((ReadFailureException)rfe).dataPresent ? 1 : 0));
                    }
                    break;
                case WRITE_TIMEOUT:
                case READ_TIMEOUT:
                    RequestTimeoutException rte = (RequestTimeoutException)err;
                    boolean isWrite = err.code() == ExceptionCode.WRITE_TIMEOUT;

                    CBUtil.writeConsistencyLevel(rte.consistency, dest);
                    dest.writeInt(rte.received);
                    dest.writeInt(rte.blockFor);
                    if (isWrite)
                        CBUtil.writeString(((WriteTimeoutException)rte).writeType.toString(), dest);
                    else
                        dest.writeByte((byte)(((ReadTimeoutException)rte).dataPresent ? 1 : 0));
                    break;
                case FUNCTION_FAILURE:
                    FunctionExecutionException fee = (FunctionExecutionException)msg.error;
                    CBUtil.writeString(fee.functionName.keyspace, dest);
                    CBUtil.writeString(fee.functionName.name, dest);
                    CBUtil.writeStringList(fee.argTypes, dest);
                    break;
                case UNPREPARED:
                    PreparedQueryNotFoundException pqnfe = (PreparedQueryNotFoundException)err;
                    CBUtil.writeBytes(pqnfe.id.bytes, dest);
                    break;
                case ALREADY_EXISTS:
                    AlreadyExistsException aee = (AlreadyExistsException)err;
                    CBUtil.writeString(aee.ksName, dest);
                    CBUtil.writeString(aee.cfName, dest);
                    break;
            }
        }

        public int encodedSize(ErrorMessage msg, ProtocolVersion version)
        {
            final TransportException err = getBackwardsCompatibleException(msg, version);
            String errorString = err.getMessage() == null ? "" : err.getMessage();
            int size = 4 + CBUtil.sizeOfString(errorString);
            switch (err.code())
            {
                case UNAVAILABLE:
                    UnavailableException ue = (UnavailableException)err;
                    size += CBUtil.sizeOfConsistencyLevel(ue.consistency) + 8;
                    break;
                case WRITE_FAILURE:
                case READ_FAILURE:
                    {
                        RequestFailureException rfe = (RequestFailureException)err;
                        boolean isWrite = err.code() == ExceptionCode.WRITE_FAILURE;
                        size += CBUtil.sizeOfConsistencyLevel(rfe.consistency) + 4 + 4 + 4;
                        size += isWrite ? CBUtil.sizeOfString(((WriteFailureException)rfe).writeType.toString()) : 1;

                        if (version.isGreaterOrEqualTo(ProtocolVersion.V5))
                        {
                            for (Map.Entry<InetAddress, RequestFailureReason> entry : rfe.failureReasonByEndpoint.entrySet())
                            {
                                size += CBUtil.sizeOfInetAddr(entry.getKey());
                                size += 2; // RequestFailureReason code
                            }
                        }
                    }
                    break;
                case WRITE_TIMEOUT:
                case READ_TIMEOUT:
                    RequestTimeoutException rte = (RequestTimeoutException)err;
                    boolean isWrite = err.code() == ExceptionCode.WRITE_TIMEOUT;
                    size += CBUtil.sizeOfConsistencyLevel(rte.consistency) + 8;
                    size += isWrite ? CBUtil.sizeOfString(((WriteTimeoutException)rte).writeType.toString()) : 1;
                    break;
                case FUNCTION_FAILURE:
                    FunctionExecutionException fee = (FunctionExecutionException)msg.error;
                    size += CBUtil.sizeOfString(fee.functionName.keyspace);
                    size += CBUtil.sizeOfString(fee.functionName.name);
                    size += CBUtil.sizeOfStringList(fee.argTypes);
                    break;
                case UNPREPARED:
                    PreparedQueryNotFoundException pqnfe = (PreparedQueryNotFoundException)err;
                    size += CBUtil.sizeOfBytes(pqnfe.id.bytes);
                    break;
                case ALREADY_EXISTS:
                    AlreadyExistsException aee = (AlreadyExistsException)err;
                    size += CBUtil.sizeOfString(aee.ksName);
                    size += CBUtil.sizeOfString(aee.cfName);
                    break;
            }
            return size;
        }
    };

    private static TransportException getBackwardsCompatibleException(ErrorMessage msg, ProtocolVersion version)
    {
        if (version.isSmallerThan(ProtocolVersion.V4))
        {
            switch (msg.error.code())
            {
                case READ_FAILURE:
                    ReadFailureException rfe = (ReadFailureException) msg.error;
                    return new ReadTimeoutException(rfe.consistency, rfe.received, rfe.blockFor, rfe.dataPresent);
                case WRITE_FAILURE:
                    WriteFailureException wfe = (WriteFailureException) msg.error;
                    return new WriteTimeoutException(wfe.writeType, wfe.consistency, wfe.received, wfe.blockFor);
                case FUNCTION_FAILURE:
                    return new InvalidRequestException(msg.toString());
            }
        }

        return msg.error;
    }

    // We need to figure error codes out (#3979)
    public final TransportException error;

    private ErrorMessage(TransportException error)
    {
        super(Message.Type.ERROR);
        this.error = error;
    }

    private ErrorMessage(TransportException error, int streamId)
    {
        this(error);
        setStreamId(streamId);
    }

    public static ErrorMessage fromException(Throwable e)
    {
        return fromException(e, null);
    }

    /**
     * @param e the exception
     * @param unexpectedExceptionHandler a callback for handling unexpected exceptions. If null, or if this
     *                                   returns false, the error is logged at ERROR level via sl4fj
     */
    public static ErrorMessage fromException(Throwable e, Predicate<Throwable> unexpectedExceptionHandler)
    {
        int streamId = 0;

        // Netty will wrap exceptions during decoding in a CodecException. If the cause was one of our ProtocolExceptions
        // or some other internal exception, extract that and use it.
        if (e instanceof CodecException)
        {
            Throwable cause = e.getCause();
            if (cause != null)
            {
                if (cause instanceof WrappedException)
                {
                    streamId = ((WrappedException) cause).streamId;
                    e = cause.getCause();
                }
                else if (cause instanceof TransportException)
                {
                    e = cause;
                }
            }
        }
        else if (e instanceof WrappedException)
        {
            streamId = ((WrappedException)e).streamId;
            e = e.getCause();
        }

        if (e instanceof TransportException)
        {
            ErrorMessage message = new ErrorMessage((TransportException) e, streamId);
            if (e instanceof ProtocolException)
            {
                // if the driver attempted to connect with a protocol version not supported then
                // reply with the appropiate version, see ProtocolVersion.decode()
                ProtocolVersion forcedProtocolVersion = ((ProtocolException) e).getForcedProtocolVersion();
                if (forcedProtocolVersion != null)
                    message.forcedProtocolVersion = forcedProtocolVersion;
            }
            return message;
        }

        // Unexpected exception
        if (unexpectedExceptionHandler == null || !unexpectedExceptionHandler.apply(e))
            logger.error("Unexpected exception during request", e);

        return new ErrorMessage(new ServerError(e), streamId);
    }

    @Override
    public String toString()
    {
        return "ERROR " + error.code() + ": " + error.getMessage();
    }

    public static RuntimeException wrap(Throwable t, int streamId)
    {
        return new WrappedException(t, streamId);
    }

    public static class WrappedException extends RuntimeException
    {
        private final int streamId;

        public WrappedException(Throwable cause, int streamId)
        {
            super(cause);
            this.streamId = streamId;
        }

        @VisibleForTesting
        public int getStreamId()
        {
            return this.streamId;
        }
    }

}
