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

#ifndef DATASTAX_INTERNAL_RESOLVER_HPP
#define DATASTAX_INTERNAL_RESOLVER_HPP

#include "address.hpp"
#include "callback.hpp"
#include "ref_counted.hpp"
#include "string.hpp"
#include "timer.hpp"
#include "vector.hpp"

#include <uv.h>

#include <functional>

namespace datastax { namespace internal { namespace core {

class Resolver : public RefCounted<Resolver> {
public:
  typedef SharedRefPtr<Resolver> Ptr;
  typedef Vector<Ptr> Vec;
  typedef internal::Callback<void, Resolver*> Callback;

  enum Status {
    NEW,
    RESOLVING,
    FAILED_BAD_PARAM,
    FAILED_UNSUPPORTED_ADDRESS_FAMILY,
    FAILED_UNABLE_TO_RESOLVE,
    FAILED_TIMED_OUT,
    CANCELED,
    SUCCESS
  };

  Resolver(const String& hostname, int port, const Callback& callback)
      : hostname_(hostname)
      , port_(port)
      , status_(NEW)
      , callback_(callback) {
    req_.data = this;
  }

  uv_loop_t* loop() { return req_.loop; }

  const String& hostname() { return hostname_; }
  int port() { return port_; }

  bool is_canceled() { return status_ == CANCELED; }
  bool is_success() { return status_ == SUCCESS; }
  bool is_timed_out() { return status_ == FAILED_TIMED_OUT; }
  Status status() { return status_; }
  int uv_status() { return uv_status_; }

  const AddressVec& addresses() const { return addresses_; }

  void resolve(uv_loop_t* loop, uint64_t timeout, struct addrinfo* hints = NULL) {
    status_ = RESOLVING;

    inc_ref(); // For the event loop

    // If no hints are provided then use a default filter.
    struct addrinfo default_hints;
    if (hints == NULL) {
      hints = &default_hints;
      memset(hints, 0, sizeof(struct addrinfo));
      hints->ai_family = AF_UNSPEC;
      hints->ai_socktype = SOCK_STREAM;
    }

    if (timeout > 0) {
      timer_.start(loop, timeout, bind_callback(&Resolver::on_timeout, this));
    }

    OStringStream ss;
    ss << port_;
    int rc = uv_getaddrinfo(loop, &req_, on_resolve, hostname_.c_str(), ss.str().c_str(), hints);

    if (rc != 0) {
      status_ = FAILED_BAD_PARAM;
      timer_.stop();
      uv_status_ = rc;
      callback_(this);
      dec_ref();
    }
  }

  void cancel() {
    if (status_ == RESOLVING) {
      uv_cancel(reinterpret_cast<uv_req_t*>(&req_));
      timer_.stop();
      status_ = CANCELED;
    }
  }

private:
  static void on_resolve(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
    Resolver* resolver = static_cast<Resolver*>(req->data);

    if (resolver->status_ == RESOLVING) { // A timeout may have happened
      resolver->timer_.stop();

      if (status != 0) {
        resolver->status_ = FAILED_UNABLE_TO_RESOLVE;
      } else if (!resolver->init_addresses(res)) {
        resolver->status_ = FAILED_UNSUPPORTED_ADDRESS_FAMILY;
      } else {
        resolver->status_ = SUCCESS;
      }
    }

    resolver->uv_status_ = status;
    resolver->callback_(resolver);
    resolver->dec_ref();
    uv_freeaddrinfo(res);
  }

  void on_timeout(Timer* timer) {
    timer_.stop();
    status_ = FAILED_TIMED_OUT;
    uv_cancel(reinterpret_cast<uv_req_t*>(&req_));
  }

private:
  bool init_addresses(struct addrinfo* res) {
    bool status = false;
    do {
      Address address(res->ai_addr);
      if (address.is_valid_and_resolved()) {
        addresses_.push_back(address);
        status = true;
      }
      res = res->ai_next;
    } while (res);
    return status;
  }

private:
  uv_getaddrinfo_t req_;
  Timer timer_;
  String hostname_;
  int port_;
  Status status_;
  int uv_status_;
  AddressVec addresses_;
  Callback callback_;

private:
  DISALLOW_COPY_AND_ASSIGN(Resolver);
};

class MultiResolver : public RefCounted<MultiResolver> {
public:
  typedef SharedRefPtr<MultiResolver> Ptr;
  typedef internal::Callback<void, MultiResolver*> Callback;

  MultiResolver(const Callback& callback)
      : remaining_(0)
      , callback_(callback) {}

  const Resolver::Vec& resolvers() { return resolvers_; }

  void resolve(uv_loop_t* loop, const String& host, int port, uint64_t timeout,
               struct addrinfo* hints = NULL) {
    inc_ref();
    Resolver::Ptr resolver(
        new Resolver(host, port, bind_callback(&MultiResolver::on_resolve, this)));
    resolver->resolve(loop, timeout, hints);
    resolvers_.push_back(resolver);
    remaining_++;
  }

  void cancel() {
    for (Resolver::Vec::iterator it = resolvers_.begin(), end = resolvers_.end(); it != end; ++it) {
      (*it)->cancel();
    }
  }

private:
  void on_resolve(Resolver* resolver) {
    remaining_--;
    if (remaining_ <= 0 && callback_) {
      callback_(this);
    }
    dec_ref();
  }

private:
  Resolver::Vec resolvers_;
  int remaining_;
  Callback callback_;

private:
  DISALLOW_COPY_AND_ASSIGN(MultiResolver);
};

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

#endif
