/*
  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 "control_connector.hpp"
#include "result_iterator.hpp"

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

namespace datastax { namespace internal { namespace core {

/**
 * A chained request callback that gets the cluster's hosts from the
 * "system.local" and "system.peers" tables.
 */
class HostsConnectorRequestCallback : public ChainedRequestCallback {
public:
  typedef SharedRefPtr<HostsConnectorRequestCallback> Ptr;

  HostsConnectorRequestCallback(const String& key, const String& query, ControlConnector* connector)
      : ChainedRequestCallback(key, query)
      , connector_(connector) {}

  virtual void on_chain_set() { connector_->handle_query_hosts(this); }

  virtual void on_chain_error(CassError code, const String& message) {
    connector_->on_error(ControlConnector::CONTROL_CONNECTION_ERROR_HOSTS,
                         "Error running host queries on control connection: " + message);
  }

  virtual void on_chain_timeout() {
    connector_->on_error(ControlConnector::CONTROL_CONNECTION_ERROR_HOSTS,
                         "Timed out running host queries on control connection");
  }

private:
  ControlConnector* connector_;
};

/**
 * A chained request callback that gets the cluster's schema metadata.
 */
class SchemaConnectorRequestCallback : public ChainedRequestCallback {
public:
  typedef SharedRefPtr<SchemaConnectorRequestCallback> Ptr;

  SchemaConnectorRequestCallback(const String& key, const String& query,
                                 ControlConnector* connector)
      : ChainedRequestCallback(key, query)
      , connector_(connector) {}

  virtual void on_chain_set() { connector_->handle_query_schema(this); }

  virtual void on_chain_error(CassError code, const String& message) {
    connector_->on_error(ControlConnector::CONTROL_CONNECTION_ERROR_SCHEMA,
                         "Error running schema queries on control connection " + message);
  }

  virtual void on_chain_timeout() {
    connector_->on_error(ControlConnector::CONTROL_CONNECTION_ERROR_SCHEMA,
                         "Timed out running schema queries on control connection");
  }

private:
  ControlConnector* connector_;
};

}}} // namespace datastax::internal::core

ControlConnector* ControlConnector::with_listener(ControlConnectionListener* listener) {
  listener_ = listener;
  return this;
}

ControlConnector* ControlConnector::with_metrics(Metrics* metrics) {
  metrics_ = metrics;
  return this;
}

ControlConnector* ControlConnector::with_settings(const ControlConnectionSettings& settings) {
  settings_ = settings;
  return this;
}

void ControlConnector::connect(uv_loop_t* loop) {
  inc_ref();
  int event_types = 0;
  if (settings_.use_schema || settings_.use_token_aware_routing) {
    event_types = CASS_EVENT_TOPOLOGY_CHANGE | CASS_EVENT_STATUS_CHANGE | CASS_EVENT_SCHEMA_CHANGE;
  } else {
    event_types = CASS_EVENT_TOPOLOGY_CHANGE | CASS_EVENT_STATUS_CHANGE;
  }
  connector_->with_metrics(metrics_)
      ->with_settings(settings_.connection_settings)
      ->with_event_types(event_types)
      ->connect(loop);
}

void ControlConnector::cancel() {
  error_code_ = CONTROL_CONNECTION_CANCELED;
  connector_->cancel();
  if (connection_) connection_->close();
  if (control_connection_) control_connection_->close();
}

ControlConnection::Ptr ControlConnector::release_connection() {
  ControlConnection::Ptr temp(control_connection_);
  control_connection_.reset();
  return temp;
}

void ControlConnector::finish() {
  if (connection_) connection_->set_listener();
  callback_(this);
  // If the connections haven't been released then close them.
  if (connection_) connection_->close();
  if (control_connection_) {
    // If the callback doesn't take possession of the connection then we should
    // also clear the listener.
    control_connection_->set_listener();
    control_connection_->close();
  }
  dec_ref();
}

void ControlConnector::on_success() {
  if (is_canceled()) {
    finish();
    return;
  }

  // Transfer ownership of the connection to the control connection.
  control_connection_.reset(new ControlConnection(
      connection_, listener_, settings_, server_version_, dse_server_version_, listen_addresses_));

  control_connection_->set_listener(listener_);

  // Process any events that happened during control connection setup. It's
  // important to capture any changes that happened during retrieving the
  // host and schema metadata that might not be reflected in that data.
  ControlConnector::process_events(events(), control_connection_.get());

  connection_.reset(); // The control connection now owns it.

  finish();
}

void ControlConnector::on_error(ControlConnector::ControlConnectionError code,
                                const String& message) {
  assert(code != CONTROL_CONNECTION_OK && "Notified error without an error");
  if (error_code_ == CONTROL_CONNECTION_OK) { // Only perform this once
    error_message_ = message;
    error_code_ = code;
    if (connection_) connection_->defunct();
    finish();
  }
}

void ControlConnector::on_connect(Connector* connector) {
  if (!is_canceled() && connector->is_ok()) {
    connection_ = connector->release_connection();

    // It's important to record any events that happen while querying the hosts
    // and schema. The recorded events are replayed after the initial hosts
    // and schema are returned and processed.
    connection_->set_listener(this);

    query_hosts();
  } else if (is_canceled() || connector->is_canceled()) {
    finish();
  } else if (connector->error_code() == Connector::CONNECTION_ERROR_CLOSE) {
    on_error(CONTROL_CONNECTION_ERROR_CLOSE, connector->error_message());
  } else {
    on_error(CONTROL_CONNECTION_ERROR_CONNECTION,
             "Underlying connection error: " + connector->error_message());
  }
}

void ControlConnector::query_hosts() {
  // This needs to happen before other schema metadata queries so that we have
  // a valid server version because this version determines which follow up
  // schema metadata queries are executed.
  ChainedRequestCallback::Ptr callback(
      new HostsConnectorRequestCallback("local", SELECT_LOCAL, this));
  callback = callback->chain("peers", SELECT_PEERS);

  if (connection_->write_and_flush(callback) < 0) {
    on_error(CONTROL_CONNECTION_ERROR_HOSTS, "Unable able to write hosts query to connection");
  }
}

void ControlConnector::handle_query_hosts(HostsConnectorRequestCallback* callback) {
  ResultResponse::Ptr local_result(callback->result("local"));
  const Host::Ptr& connected_host = connection_->host();
  if (local_result && local_result->row_count() > 0) {
    connected_host->set(&local_result->first_row(), settings_.use_token_aware_routing);
    hosts_[connected_host->address()] = connected_host;
    server_version_ = connected_host->server_version();
    dse_server_version_ = connected_host->dse_server_version();
  } else {
    on_error(CONTROL_CONNECTION_ERROR_HOSTS,
             "No row found in " + connection_->address_string() + "'s local system table");
    return;
  }

  ResultResponse::Ptr peers_result(callback->result("peers"));
  if (peers_result) {
    ResultIterator rows(peers_result.get());
    while (rows.next()) {
      Address address;
      const Row* row = rows.row();
      if (settings_.address_factory->create(row, connected_host, &address)) {
        Host::Ptr host(new Host(address));
        host->set(rows.row(), settings_.use_token_aware_routing);
        listen_addresses_[host->rpc_address()] = determine_listen_address(address, row);
        hosts_[host->address()] = host;
      }
    }
  }

  if (settings_.use_token_aware_routing || settings_.use_schema) {
    query_schema();
  } else {
    // If we're not using token aware routing or schema we can just finish.
    on_success();
  }
}

void ControlConnector::query_schema() {
  ChainedRequestCallback::Ptr callback;

  if (server_version_ >= VersionNumber(3, 0, 0)) {
    callback = ChainedRequestCallback::Ptr(
        new SchemaConnectorRequestCallback("keyspaces", SELECT_KEYSPACES_30, this));
    if (settings_.use_schema) {
      callback = callback->chain("tables", SELECT_TABLES_30)
                     ->chain("views", SELECT_VIEWS_30)
                     ->chain("columns", SELECT_COLUMNS_30)
                     ->chain("indexes", SELECT_INDEXES_30)
                     ->chain("user_types", SELECT_USERTYPES_30)
                     ->chain("functions", SELECT_FUNCTIONS_30)
                     ->chain("aggregates", SELECT_AGGREGATES_30);

      if (server_version_ >= VersionNumber(4, 0, 0)) {
        callback = callback->chain("virtual_keyspaces", SELECT_VIRTUAL_KEYSPACES_40)
                       ->chain("virtual_tables", SELECT_VIRTUAL_TABLES_40)
                       ->chain("virtual_columns", SELECT_VIRTUAL_COLUMNS_40);
      }
    }
  } else {
    callback = ChainedRequestCallback::Ptr(
        new SchemaConnectorRequestCallback("keyspaces", SELECT_KEYSPACES_20, this));
    if (settings_.use_schema) {
      callback =
          callback->chain("tables", SELECT_COLUMN_FAMILIES_20)->chain("columns", SELECT_COLUMNS_20);

      if (server_version_ >= VersionNumber(2, 1, 0)) {
        callback = callback->chain("user_types", SELECT_USERTYPES_21);
      }
      if (server_version_ >= VersionNumber(2, 2, 0)) {
        callback = callback->chain("functions", SELECT_FUNCTIONS_22)
                       ->chain("aggregates", SELECT_AGGREGATES_22);
      }
    }
  }

  if (connection_->write_and_flush(callback) < 0) {
    on_error(CONTROL_CONNECTION_ERROR_SCHEMA, "Unable able to write schema query to connection");
  }
}

void ControlConnector::handle_query_schema(SchemaConnectorRequestCallback* callback) {
  schema_.keyspaces = callback->result("keyspaces");
  schema_.tables = callback->result("tables");
  schema_.views = callback->result("views");
  schema_.columns = callback->result("columns");
  schema_.indexes = callback->result("indexes");
  schema_.user_types = callback->result("user_types");
  schema_.functions = callback->result("functions");
  schema_.aggregates = callback->result("aggregates");
  schema_.virtual_keyspaces = callback->result("virtual_keyspaces");
  schema_.virtual_tables = callback->result("virtual_tables");
  schema_.virtual_columns = callback->result("virtual_columns");

  on_success();
}

void ControlConnector::on_close(Connection* connection) {
  if (is_canceled()) {
    finish();
  } else {
    on_error(CONTROL_CONNECTION_ERROR_CLOSE, "Control connection closed prematurely");
  }
}
