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

#include "statement.hpp"

#include "collection.hpp"
#include "execute_request.hpp"
#include "external.hpp"
#include "macros.hpp"
#include "prepared.hpp"
#include "protocol.hpp"
#include "query_request.hpp"
#include "request_callback.hpp"
#include "scoped_ptr.hpp"
#include "string_ref.hpp"
#include "tuple.hpp"
#include "user_type_value.hpp"

#include <uv.h>

using namespace datastax;
using namespace datastax::internal;
using namespace datastax::internal::core;

extern "C" {

CassStatement* cass_statement_new(const char* query, size_t parameter_count) {
  return cass_statement_new_n(query, SAFE_STRLEN(query), parameter_count);
}

CassStatement* cass_statement_new_n(const char* query, size_t query_length,
                                    size_t parameter_count) {
  QueryRequest* query_request = new QueryRequest(query, query_length, parameter_count);
  query_request->inc_ref();
  return CassStatement::to(query_request);
}

CassError cass_statement_reset_parameters(CassStatement* statement, size_t count) {
  statement->reset(count);
  return CASS_OK;
}

CassError cass_statement_add_key_index(CassStatement* statement, size_t index) {
  if (statement->kind() != CASS_BATCH_KIND_QUERY) return CASS_ERROR_LIB_BAD_PARAMS;
  if (index >= statement->elements().size()) return CASS_ERROR_LIB_BAD_PARAMS;
  statement->add_key_index(index);
  return CASS_OK;
}

CassError cass_statement_set_keyspace(CassStatement* statement, const char* keyspace) {
  return cass_statement_set_keyspace_n(statement, keyspace, SAFE_STRLEN(keyspace));
}

CassError cass_statement_set_keyspace_n(CassStatement* statement, const char* keyspace,
                                        size_t keyspace_length) {
  // The keyspace is set by the prepared metadata
  if (statement->opcode() == CQL_OPCODE_EXECUTE) {
    return CASS_ERROR_LIB_BAD_PARAMS;
  }
  statement->set_keyspace(String(keyspace, keyspace_length));
  return CASS_OK;
}

void cass_statement_free(CassStatement* statement) { statement->dec_ref(); }

CassError cass_statement_set_consistency(CassStatement* statement, CassConsistency consistency) {
  statement->set_consistency(consistency);
  return CASS_OK;
}

CassError cass_statement_set_serial_consistency(CassStatement* statement,
                                                CassConsistency serial_consistency) {
  statement->set_serial_consistency(serial_consistency);
  return CASS_OK;
}

CassError cass_statement_set_paging_size(CassStatement* statement, int page_size) {
  statement->set_page_size(page_size);
  return CASS_OK;
}

CassError cass_statement_set_paging_state(CassStatement* statement, const CassResult* result) {
  statement->set_paging_state(result->paging_state().to_string());
  return CASS_OK;
}

CassError cass_statement_set_paging_state_token(CassStatement* statement, const char* paging_state,
                                                size_t paging_state_size) {
  statement->set_paging_state(String(paging_state, paging_state_size));
  return CASS_OK;
}

CassError cass_statement_set_retry_policy(CassStatement* statement, CassRetryPolicy* retry_policy) {
  statement->set_retry_policy(retry_policy);
  return CASS_OK;
}

CassError cass_statement_set_timestamp(CassStatement* statement, cass_int64_t timestamp) {
  statement->set_timestamp(timestamp);
  return CASS_OK;
}

CassError cass_statement_set_request_timeout(CassStatement* statement, cass_uint64_t timeout_ms) {
  statement->set_request_timeout_ms(timeout_ms);
  return CASS_OK;
}

CassError cass_statement_set_is_idempotent(CassStatement* statement, cass_bool_t is_idempotent) {
  statement->set_is_idempotent(is_idempotent == cass_true);
  return CASS_OK;
}

CassError cass_statement_set_custom_payload(CassStatement* statement,
                                            const CassCustomPayload* payload) {
  statement->set_custom_payload(payload);
  return CASS_OK;
}

CassError cass_statement_set_execution_profile(CassStatement* statement, const char* name) {
  return cass_statement_set_execution_profile_n(statement, name, SAFE_STRLEN(name));
}

CassError cass_statement_set_execution_profile_n(CassStatement* statement, const char* name,
                                                 size_t name_length) {
  if (name_length > 0) {
    statement->set_execution_profile_name(String(name, name_length));
  } else {
    statement->set_execution_profile_name(String());
  }
  return CASS_OK;
}

CassError cass_statement_set_tracing(CassStatement* statement, cass_bool_t enabled) {
  statement->set_tracing(enabled == cass_true);
  return CASS_OK;
}

CassError cass_statement_set_host(CassStatement* statement, const char* host, int port) {
  return cass_statement_set_host_n(statement, host, SAFE_STRLEN(host), port);
}

CassError cass_statement_set_host_n(CassStatement* statement, const char* host, size_t host_length,
                                    int port) {
  Address address(String(host, host_length), port);
  if (!address.is_valid_and_resolved()) {
    return CASS_ERROR_LIB_BAD_PARAMS;
  }
  statement->set_host(address);
  return CASS_OK;
}

CassError cass_statement_set_host_inet(CassStatement* statement, const CassInet* host, int port) {
  Address address(host->address, host->address_length, port);
  if (!address.is_valid_and_resolved()) {
    return CASS_ERROR_LIB_BAD_PARAMS;
  }
  statement->set_host(address);
  return CASS_OK;
}

CassError cass_statement_set_node(CassStatement* statement, const CassNode* node) {
  if (node == NULL) {
    return CASS_ERROR_LIB_BAD_PARAMS;
  }
  statement->set_host(*node->from());
  return CASS_OK;
}

#define CASS_STATEMENT_BIND(Name, Params, Value)                                               \
  CassError cass_statement_bind_##Name(CassStatement* statement, size_t index Params) {        \
    return statement->set(index, Value);                                                       \
  }                                                                                            \
  CassError cass_statement_bind_##Name##_by_name(CassStatement* statement,                     \
                                                 const char* name Params) {                    \
    return statement->set(StringRef(name), Value);                                             \
  }                                                                                            \
  CassError cass_statement_bind_##Name##_by_name_n(CassStatement* statement, const char* name, \
                                                   size_t name_length Params) {                \
    return statement->set(StringRef(name, name_length), Value);                                \
  }

CASS_STATEMENT_BIND(null, ZERO_PARAMS_(), CassNull())
CASS_STATEMENT_BIND(int8, ONE_PARAM_(cass_int8_t value), value)
CASS_STATEMENT_BIND(int16, ONE_PARAM_(cass_int16_t value), value)
CASS_STATEMENT_BIND(int32, ONE_PARAM_(cass_int32_t value), value)
CASS_STATEMENT_BIND(uint32, ONE_PARAM_(cass_uint32_t value), value)
CASS_STATEMENT_BIND(int64, ONE_PARAM_(cass_int64_t value), value)
CASS_STATEMENT_BIND(float, ONE_PARAM_(cass_float_t value), value)
CASS_STATEMENT_BIND(double, ONE_PARAM_(cass_double_t value), value)
CASS_STATEMENT_BIND(bool, ONE_PARAM_(cass_bool_t value), value)
CASS_STATEMENT_BIND(uuid, ONE_PARAM_(CassUuid value), value)
CASS_STATEMENT_BIND(inet, ONE_PARAM_(CassInet value), value)
CASS_STATEMENT_BIND(collection, ONE_PARAM_(const CassCollection* value), value->from())
CASS_STATEMENT_BIND(tuple, ONE_PARAM_(const CassTuple* value), value->from())
CASS_STATEMENT_BIND(user_type, ONE_PARAM_(const CassUserType* value), value->from())
CASS_STATEMENT_BIND(bytes, TWO_PARAMS_(const cass_byte_t* value, size_t value_size),
                    CassBytes(value, value_size))
CASS_STATEMENT_BIND(decimal,
                    THREE_PARAMS_(const cass_byte_t* varint, size_t varint_size, int scale),
                    CassDecimal(varint, varint_size, scale))
CASS_STATEMENT_BIND(duration,
                    THREE_PARAMS_(cass_int32_t months, cass_int32_t days, cass_int64_t nanos),
                    CassDuration(months, days, nanos))

#undef CASS_STATEMENT_BIND

CassError cass_statement_bind_string(CassStatement* statement, size_t index, const char* value) {
  return cass_statement_bind_string_n(statement, index, value, SAFE_STRLEN(value));
}

CassError cass_statement_bind_string_n(CassStatement* statement, size_t index, const char* value,
                                       size_t value_length) {
  return statement->set(index, CassString(value, value_length));
}

CassError cass_statement_bind_string_by_name(CassStatement* statement, const char* name,
                                             const char* value) {
  return statement->set(StringRef(name), CassString(value, SAFE_STRLEN(value)));
}

CassError cass_statement_bind_string_by_name_n(CassStatement* statement, const char* name,
                                               size_t name_length, const char* value,
                                               size_t value_length) {
  return statement->set(StringRef(name, name_length), CassString(value, value_length));
}

CassError cass_statement_bind_custom(CassStatement* statement, size_t index, const char* class_name,
                                     const cass_byte_t* value, size_t value_size) {
  return statement->set(index, CassCustom(StringRef(class_name), value, value_size));
}

CassError cass_statement_bind_custom_n(CassStatement* statement, size_t index,
                                       const char* class_name, size_t class_name_length,
                                       const cass_byte_t* value, size_t value_size) {
  return statement->set(index,
                        CassCustom(StringRef(class_name, class_name_length), value, value_size));
}

CassError cass_statement_bind_custom_by_name(CassStatement* statement, const char* name,
                                             const char* class_name, const cass_byte_t* value,
                                             size_t value_size) {
  return statement->set(StringRef(name), CassCustom(StringRef(class_name), value, value_size));
}

CassError cass_statement_bind_custom_by_name_n(CassStatement* statement, const char* name,
                                               size_t name_length, const char* class_name,
                                               size_t class_name_length, const cass_byte_t* value,
                                               size_t value_size) {
  return statement->set(StringRef(name, name_length),
                        CassCustom(StringRef(class_name, class_name_length), value, value_size));
}

} // extern "C"

Statement::Statement(const char* query, size_t query_length, size_t values_count)
    : RoutableRequest(CQL_OPCODE_QUERY)
    , AbstractData(values_count)
    , query_or_id_(sizeof(int32_t) + query_length)
    , flags_(0)
    , page_size_(-1) {
  // <query> [long string]
  query_or_id_.encode_long_string(0, query, query_length);
}

Statement::Statement(const Prepared* prepared)
    : RoutableRequest(CQL_OPCODE_EXECUTE)
    , AbstractData(prepared->result()->column_count())
    , query_or_id_(sizeof(uint16_t) + prepared->id().size())
    , flags_(0)
    , page_size_(-1) {
  // <id> [short bytes] (or [string])
  const String& id = prepared->id();
  query_or_id_.encode_string(0, id.data(), static_cast<uint16_t>(id.size()));
  // Inherit settings and keyspace from the prepared statement
  set_settings(prepared->request_settings());
  // If the keyspace wasn't explictly set then attempt to set it using the
  // prepared statement's result metadata.
  if (keyspace().empty()) {
    set_keyspace(prepared->result()->quoted_keyspace());
  }
}

String Statement::query() const {
  if (opcode() == CQL_OPCODE_QUERY) {
    return String(query_or_id_.data() + sizeof(int32_t), query_or_id_.size() - sizeof(int32_t));
  }
  return String();
}

// Format: <kind><string_or_id><n><value_1>...<value_n>
// where:
// <kind> is a [byte]
// <string_or_id> is a [long string] for <string> and a [short bytes] for <id>
// <n> is a [short]
// <value> is a [bytes]
int32_t Statement::encode_batch(ProtocolVersion version, RequestCallback* callback,
                                BufferVec* bufs) const {
  int32_t length = 0;

  { // <kind> [byte]
    bufs->push_back(Buffer(sizeof(uint8_t)));
    Buffer& buf = bufs->back();
    buf.encode_byte(0, kind());
    length += sizeof(uint8_t);
  }

  bufs->push_back(query_or_id_);
  length += query_or_id_.size();

  { // <n> [short]
    bufs->push_back(Buffer(sizeof(uint16_t)));
    Buffer& buf = bufs->back();
    buf.encode_uint16(0, static_cast<uint16_t>(elements().size()));
    length += sizeof(uint16_t);
  }

  if (elements().size() > 0) {
    int32_t result = encode_values(version, callback, bufs);
    if (result < 0) return result;
    length += result;
  }

  return length;
}

bool Statement::with_keyspace(ProtocolVersion version) const {
  return version.supports_set_keyspace() &&
         // Execute requests (bound statements) use the keyspace
         // from the time of prepare.
         opcode() != CQL_OPCODE_EXECUTE && !keyspace().empty();
}

// For query statements the format is:
// <query><consistency><flags><n>
// where:
// <query> has the format [long string]
// <consistency> is a [short]
// <flags> is a [byte] (or [int] for protocol v5)
// <n> is a [short]
//
// For execute statements the format is:
// <id><consistency><flags><n>
// where:
// <id> has the format [short bytes] (or [string])
// <consistency> is a [short]
// <flags> is a [byte] (or [int] for protocol v5)
// <n> is a [short]

int32_t Statement::encode_query_or_id(BufferVec* bufs) const {
  bufs->push_back(query_or_id_);
  return query_or_id_.size();
}

int32_t Statement::encode_begin(ProtocolVersion version, uint16_t element_count,
                                RequestCallback* callback, BufferVec* bufs) const {
  int32_t length = 0;
  size_t query_params_buf_size = 0;
  int32_t flags = flags_;

  if (callback->skip_metadata()) {
    flags |= CASS_QUERY_FLAG_SKIP_METADATA;
  }

  query_params_buf_size += sizeof(uint16_t); // <consistency> [short]

  if (version >= CASS_PROTOCOL_VERSION_V5) {
    query_params_buf_size += sizeof(int32_t); // <flags> [int]
  } else {
    query_params_buf_size += sizeof(uint8_t); // <flags> [byte]
  }

  if (element_count > 0) {
    query_params_buf_size += sizeof(uint16_t); // <n> [short]
    flags |= CASS_QUERY_FLAG_VALUES;
  }

  if (page_size() > 0) {
    flags |= CASS_QUERY_FLAG_PAGE_SIZE;
  }

  if (!paging_state().empty()) {
    flags |= CASS_QUERY_FLAG_PAGING_STATE;
  }

  if (callback->serial_consistency() != 0) {
    flags |= CASS_QUERY_FLAG_SERIAL_CONSISTENCY;
  }

  if (callback->timestamp() != CASS_INT64_MIN) {
    flags |= CASS_QUERY_FLAG_DEFAULT_TIMESTAMP;
  }

  if (with_keyspace(version)) {
    flags |= CASS_QUERY_FLAG_WITH_KEYSPACE;
  }

  bufs->push_back(Buffer(query_params_buf_size));
  length += query_params_buf_size;

  Buffer& buf = bufs->back();
  size_t pos = buf.encode_uint16(0, callback->consistency());

  if (version >= CASS_PROTOCOL_VERSION_V5) {
    pos = buf.encode_int32(pos, flags);
  } else {
    pos = buf.encode_byte(pos, static_cast<uint8_t>(flags));
  }

  if (element_count > 0) {
    buf.encode_uint16(pos, element_count);
  }

  return length;
}

// Format: [<value_1>...<value_n>]
// where:
// <value> is a [bytes]
int32_t Statement::encode_values(ProtocolVersion version, RequestCallback* callback,
                                 BufferVec* bufs) const {
  int32_t length = 0;
  for (size_t i = 0; i < elements().size(); ++i) {
    const Element& element = elements()[i];
    if (!element.is_unset()) {
      bufs->push_back(element.get_buffer());
    } else {
      if (version >= CASS_PROTOCOL_VERSION_V4) {
        bufs->push_back(core::encode_with_length(CassUnset()));
      } else {
        OStringStream ss;
        ss << "Query parameter at index " << i << " was not set";
        callback->on_error(CASS_ERROR_LIB_PARAMETER_UNSET, ss.str());
        return Request::REQUEST_ERROR_PARAMETER_UNSET;
      }
    }
    length += bufs->back().size();
  }
  return length;
}

// Format: [<result_page_size>][<paging_state>][<serial_consistency>][<timestamp>]
// where:
// <result_page_size> is a [int]
// <paging_state> is a [bytes]
// <serial_consistency> is a [short]
// <timestamp> is a [long]
// <keyspace> is a [string]
int32_t Statement::encode_end(ProtocolVersion version, RequestCallback* callback,
                              BufferVec* bufs) const {
  int32_t length = 0;
  size_t paging_buf_size = 0;

  bool with_keyspace = this->with_keyspace(version);

  if (page_size() > 0) {
    paging_buf_size += sizeof(int32_t); // [int]
  }

  if (!paging_state().empty()) {
    paging_buf_size += sizeof(int32_t) + paging_state().size(); // [bytes]
  }

  if (callback->serial_consistency() != 0) {
    paging_buf_size += sizeof(uint16_t); // [short]
  }

  if (callback->timestamp() != CASS_INT64_MIN) {
    paging_buf_size += sizeof(int64_t); // [long]
  }

  if (with_keyspace) {
    paging_buf_size += sizeof(uint16_t) + keyspace().size();
  }

  if (paging_buf_size > 0) {
    bufs->push_back(Buffer(paging_buf_size));
    length += paging_buf_size;

    Buffer& buf = bufs->back();
    size_t pos = 0;

    if (page_size() >= 0) {
      pos = buf.encode_int32(pos, page_size());
    }

    if (!paging_state().empty()) {
      pos = buf.encode_bytes(pos, paging_state().data(), paging_state().size());
    }

    if (callback->serial_consistency() != 0) {
      pos = buf.encode_uint16(pos, callback->serial_consistency());
    }

    if (callback->timestamp() != CASS_INT64_MIN) {
      pos = buf.encode_int64(pos, callback->timestamp());
    }

    if (with_keyspace) {
      pos = buf.encode_string(pos, keyspace().data(), static_cast<uint16_t>(keyspace().size()));
    }
  }

  return length;
}

bool Statement::calculate_routing_key(const Vector<size_t>& key_indices,
                                      String* routing_key) const {
  if (key_indices.empty()) return false;

  if (key_indices.size() == 1) {
    assert(key_indices.front() < elements().size());
    const AbstractData::Element& element(elements()[key_indices.front()]);
    if (element.is_unset() || element.is_null()) {
      return false;
    }
    Buffer buf(element.get_buffer());
    routing_key->assign(buf.data() + sizeof(int32_t), buf.size() - sizeof(int32_t));
  } else {
    size_t length = 0;

    for (Vector<size_t>::const_iterator i = key_indices.begin(); i != key_indices.end(); ++i) {
      assert(*i < elements().size());
      const AbstractData::Element& element(elements()[*i]);
      if (element.is_unset() || element.is_null()) {
        return false;
      }
      size_t size = element.get_size() - sizeof(int32_t);
      length += sizeof(uint16_t) + size + 1;
    }

    routing_key->clear();
    routing_key->reserve(length);

    for (Vector<size_t>::const_iterator i = key_indices.begin(); i != key_indices.end(); ++i) {
      const AbstractData::Element& element(elements()[*i]);
      Buffer buf(element.get_buffer());
      size_t size = buf.size() - sizeof(int32_t);

      char size_buf[sizeof(uint16_t)];
      encode_uint16(size_buf, static_cast<uint16_t>(size));
      routing_key->append(size_buf, sizeof(uint16_t));
      routing_key->append(buf.data() + sizeof(int32_t), size);
      routing_key->push_back(0);
    }
  }

  return true;
}
