/*
  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 "delayed_connector.hpp"

#include "event_loop.hpp"

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

DelayedConnector::DelayedConnector(const Host::Ptr& host, ProtocolVersion protocol_version,
                                   const Callback& callback)
    : connector_(
          new Connector(host, protocol_version, bind_callback(&DelayedConnector::on_connect, this)))
    , callback_(callback)
    , is_canceled_(false) {}

DelayedConnector* DelayedConnector::with_keyspace(const String& keyspace) {
  connector_->with_keyspace(keyspace);
  return this;
}

DelayedConnector* DelayedConnector::with_metrics(Metrics* metrics) {
  connector_->with_metrics(metrics);
  return this;
}

DelayedConnector* DelayedConnector::with_settings(const ConnectionSettings& settings) {
  connector_->with_settings(settings);
  return this;
}

void DelayedConnector::delayed_connect(uv_loop_t* loop, uint64_t wait_time_ms) {
  inc_ref();
  if (wait_time_ms > 0) {
    delayed_connect_timer_.start(loop, wait_time_ms,
                                 bind_callback(&DelayedConnector::on_delayed_connect, this));
  } else {
    internal_connect(loop);
  }
}

void DelayedConnector::attempt_immediate_connect() {
  if (delayed_connect_timer_.is_running() && !is_canceled_) {
    internal_connect(delayed_connect_timer_.loop());
    delayed_connect_timer_.stop();
  }
}

void DelayedConnector::cancel() {
  is_canceled_ = true;
  if (delayed_connect_timer_.is_running()) {
    delayed_connect_timer_.stop();
    callback_(this);
    dec_ref();
  } else {
    connector_->cancel();
  }
}

Connection::Ptr DelayedConnector::release_connection() { return connector_->release_connection(); }

bool DelayedConnector::is_canceled() const { return is_canceled_; }

bool DelayedConnector::is_ok() const { return !is_canceled() && connector_->is_ok(); }

bool DelayedConnector::is_critical_error() const {
  return !is_canceled() && connector_->is_critical_error();
}

bool DelayedConnector::is_keyspace_error() const {
  return !is_canceled() && connector_->is_keyspace_error();
}

Connector::ConnectionError DelayedConnector::error_code() const {
  if (is_canceled()) {
    return Connector::CONNECTION_CANCELED;
  }
  return connector_->error_code();
}

void DelayedConnector::internal_connect(uv_loop_t* loop) { connector_->connect(loop); }

void DelayedConnector::on_connect(Connector* connector) {
  callback_(this);
  dec_ref();
}

void DelayedConnector::on_delayed_connect(Timer* timer) { internal_connect(timer->loop()); }
