/*
  Copyright (c) DataStax, Inc.

  Licensed 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 "future.hpp"

#include "external.hpp"
#include "prepared.hpp"
#include "request_handler.hpp"
#include "result_response.hpp"
#include "scoped_ptr.hpp"

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

extern "C" {

void cass_future_free(CassFuture* future) {
  // Futures can be deleted without being waited on
  // because they'll be cleaned up by the notifying thread
  future->dec_ref();
}

CassError cass_future_set_callback(CassFuture* future, CassFutureCallback callback, void* data) {
  if (!future->set_callback(callback, data)) {
    return CASS_ERROR_LIB_CALLBACK_ALREADY_SET;
  }
  return CASS_OK;
}

cass_bool_t cass_future_ready(CassFuture* future) {
  return static_cast<cass_bool_t>(future->ready());
}

void cass_future_wait(CassFuture* future) { future->wait(); }

cass_bool_t cass_future_wait_timed(CassFuture* future, cass_duration_t wait_us) {
  return static_cast<cass_bool_t>(future->wait_for(wait_us));
}

const CassResult* cass_future_get_result(CassFuture* future) {
  if (future->type() != Future::FUTURE_TYPE_RESPONSE) {
    return NULL;
  }

  Response::Ptr response(static_cast<ResponseFuture*>(future->from())->response());
  if (!response || response->opcode() == CQL_OPCODE_ERROR) {
    return NULL;
  }

  response->inc_ref();
  return CassResult::to(static_cast<ResultResponse*>(response.get()));
}

const CassPrepared* cass_future_get_prepared(CassFuture* future) {
  if (future->type() != Future::FUTURE_TYPE_RESPONSE) {
    return NULL;
  }
  ResponseFuture* response_future = static_cast<ResponseFuture*>(future->from());

  SharedRefPtr<ResultResponse> result(response_future->response());
  if (!result || result->kind() != CASS_RESULT_KIND_PREPARED) {
    return NULL;
  }

  Prepared* prepared =
      new Prepared(result, response_future->prepare_request, *response_future->schema_metadata);
  prepared->inc_ref();
  return CassPrepared::to(prepared);
}

const CassErrorResult* cass_future_get_error_result(CassFuture* future) {
  if (future->type() != Future::FUTURE_TYPE_RESPONSE) {
    return NULL;
  }

  Response::Ptr response(static_cast<ResponseFuture*>(future->from())->response());
  if (!response || response->opcode() != CQL_OPCODE_ERROR) {
    return NULL;
  }

  response->inc_ref();
  return CassErrorResult::to(static_cast<ErrorResponse*>(response.get()));
}

CassError cass_future_error_code(CassFuture* future) {
  const Future::Error* error = future->error();
  if (error != NULL) {
    return error->code;
  } else {
    return CASS_OK;
  }
}

void cass_future_error_message(CassFuture* future, const char** message, size_t* message_length) {
  const Future::Error* error = future->error();
  if (error != NULL) {
    const String& m = error->message;
    *message = m.data();
    *message_length = m.length();
  } else {
    *message = "";
    *message_length = 0;
  }
}

CassError cass_future_tracing_id(CassFuture* future, CassUuid* tracing_id) {
  if (future->type() != Future::FUTURE_TYPE_RESPONSE) {
    return CASS_ERROR_LIB_INVALID_FUTURE_TYPE;
  }

  Response::Ptr response(static_cast<ResponseFuture*>(future->from())->response());
  if (!response || !response->has_tracing_id()) {
    return CASS_ERROR_LIB_NO_TRACING_ID;
  }

  *tracing_id = response->tracing_id();

  return CASS_OK;
}

size_t cass_future_custom_payload_item_count(CassFuture* future) {
  if (future->type() != Future::FUTURE_TYPE_RESPONSE) {
    return 0;
  }
  Response::Ptr response(static_cast<ResponseFuture*>(future->from())->response());
  if (!response) return 0;
  return response->custom_payload().size();
}

CassError cass_future_custom_payload_item(CassFuture* future, size_t index, const char** name,
                                          size_t* name_length, const cass_byte_t** value,
                                          size_t* value_size) {
  if (future->type() != Future::FUTURE_TYPE_RESPONSE) {
    return CASS_ERROR_LIB_INVALID_FUTURE_TYPE;
  }
  Response::Ptr response(static_cast<ResponseFuture*>(future->from())->response());
  if (!response) return CASS_ERROR_LIB_NO_CUSTOM_PAYLOAD;

  const CustomPayloadVec& custom_payload = response->custom_payload();
  if (index >= custom_payload.size()) {
    return CASS_ERROR_LIB_INDEX_OUT_OF_BOUNDS;
  }

  const CustomPayloadItem& item = custom_payload[index];
  *name = item.name.data();
  *name_length = item.name.size();
  *value = reinterpret_cast<const cass_byte_t*>(item.value.data());
  *value_size = item.value.size();
  return CASS_OK;
}

const CassNode* cass_future_coordinator(CassFuture* future) {
  if (future->type() != Future::FUTURE_TYPE_RESPONSE) {
    return NULL;
  }
  const Address& node = static_cast<ResponseFuture*>(future->from())->address();
  return node.is_valid() ? CassNode::to(&node) : NULL;
}

} // extern "C"

bool Future::set_callback(Future::Callback callback, void* data) {
  ScopedMutex lock(&mutex_);
  if (callback_) {
    return false; // Callback is already set
  }
  callback_ = callback;
  data_ = data;
  if (is_set_) {
    // Run the callback if the future is already set
    lock.unlock();
    callback(CassFuture::to(this), data);
  }
  return true;
}

void Future::internal_set(ScopedMutex& lock) {
  is_set_ = true;
  if (callback_) {
    Callback callback = callback_;
    void* data = data_;
    lock.unlock();
    callback(CassFuture::to(this), data);
    lock.lock();
  }
  // Broadcast after we've run the callback so that threads waiting
  // on this future see the side effects of the callback.
  uv_cond_broadcast(&cond_);
}
