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

#define PN_USE_DEPRECATED_API 1

#include <proton/connection.h>
#include <proton/object.h>
#include <proton/sasl.h>
#include <proton/ssl.h>
#include <proton/transport.h>
#include <proton/url.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "io.h"
#include "selectable.h"
#include "reactor.h"

// XXX: overloaded for both directions
PN_HANDLE(PN_TRANCTX)
PN_HANDLE(PNI_CONN_PEER_ADDRESS)

void pni_reactor_set_connection_peer_address(pn_connection_t *connection,
                                             const char *host,
                                             const char *port)
{
    pn_url_t *url = pn_url();
    pn_url_set_host(url, host);
    pn_url_set_port(url, port);
    pn_record_t *record = pn_connection_attachments(connection);
    if (!pn_record_has(record, PNI_CONN_PEER_ADDRESS)) {
      pn_record_def(record, PNI_CONN_PEER_ADDRESS, PN_OBJECT);
    }
    pn_record_set(record, PNI_CONN_PEER_ADDRESS, url);
    pn_decref(url);
}

static pn_transport_t *pni_transport(pn_selectable_t *sel) {
  pn_record_t *record = pn_selectable_attachments(sel);
  return (pn_transport_t *) pn_record_get(record, PN_TRANCTX);
}

static ssize_t pni_connection_capacity(pn_selectable_t *sel)
{
  pn_transport_t *transport = pni_transport(sel);
  ssize_t capacity = pn_transport_capacity(transport);
  if (capacity < 0) {
    if (pn_transport_closed(transport)) {
      pn_selectable_terminate(sel);
    }
  }
  return capacity;
}

static ssize_t pni_connection_pending(pn_selectable_t *sel)
{
  pn_transport_t *transport = pni_transport(sel);
  ssize_t pending = pn_transport_pending(transport);
  if (pending < 0) {
    if (pn_transport_closed(transport)) {
      pn_selectable_terminate(sel);
    }
  }
  return pending;
}

static pn_timestamp_t pni_connection_deadline(pn_selectable_t *sel)
{
  pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
  pn_transport_t *transport = pni_transport(sel);
  pn_timestamp_t deadline = pn_transport_tick(transport, pn_reactor_now(reactor));
  return deadline;
}

static void pni_connection_update(pn_selectable_t *sel) {
  ssize_t c = pni_connection_capacity(sel);
  ssize_t p = pni_connection_pending(sel);
  pn_selectable_set_reading(sel, c > 0);
  pn_selectable_set_writing(sel, p > 0);
  pn_selectable_set_deadline(sel, pni_connection_deadline(sel));
}

void pni_handle_transport(pn_reactor_t *reactor, pn_event_t *event) {
  assert(reactor);
  pn_transport_t *transport = pn_event_transport(event);
  pn_record_t *record = pn_transport_attachments(transport);
  pn_selectable_t *sel = (pn_selectable_t *) pn_record_get(record, PN_TRANCTX);
  if (sel && !pn_selectable_is_terminal(sel)) {
    pni_connection_update(sel);
    pn_reactor_update(reactor, sel);
  }
}

pn_selectable_t *pn_reactor_selectable_transport(pn_reactor_t *reactor, pn_socket_t sock, pn_transport_t *transport);

void pni_handle_open(pn_reactor_t *reactor, pn_event_t *event) {
  assert(reactor);
  assert(event);

  pn_connection_t *conn = pn_event_connection(event);
  if (!(pn_connection_state(conn) & PN_REMOTE_UNINIT)) {
    return;
  }

  pn_transport_t *transport = pn_transport();
  pn_transport_bind(transport, conn);
  pn_decref(transport);
}

void pni_handle_bound(pn_reactor_t *reactor, pn_event_t *event) {
  assert(reactor);
  assert(event);

  pn_connection_t *conn = pn_event_connection(event);
  pn_transport_t *transport = pn_event_transport(event);
  pn_record_t *record = pn_connection_attachments(conn);
  pn_url_t *url = (pn_url_t *)pn_record_get(record, PNI_CONN_PEER_ADDRESS);
  const char *host = NULL;
  const char *port = "5672";
  pn_string_t *str = NULL;

  // link the new transport to its reactor:
  pni_record_init_reactor(pn_transport_attachments(transport), reactor);

  if (pn_connection_acceptor(conn) != NULL) {
      // this connection was created by the acceptor.  There is already a
      // socket assigned to this connection.  Nothing needs to be done.
      return;
  }

  if (url) {
      host = pn_url_get_host(url);
      const char *uport = pn_url_get_port(url);
      if (uport) {
          port = uport;
      } else {
          const char *scheme = pn_url_get_scheme(url);
          if (scheme && strcmp(scheme, "amqps") == 0) {
              port = "5671";
          }
      }
      if (!pn_connection_get_user(conn)) {
          // user did not manually set auth info
          const char *user = pn_url_get_username(url);
          if (user) pn_connection_set_user(conn, user);
          const char *passwd = pn_url_get_password(url);
          if (passwd) pn_connection_set_password(conn, passwd);
      }
  } else {
      // for backward compatibility, see if the connection's hostname can be
      // used for the remote address.  See JIRA PROTON-1133
      const char *hostname = pn_connection_get_hostname(conn);
      if (hostname) {
          str = pn_string(hostname);
          char *h = pn_string_buffer(str);
          // see if a port has been included in the hostname.  This is not
          // allowed by the spec, but the old reactor interface allowed it.
          char *colon = strrchr(h, ':');
          if (colon) {
              *colon = '\0';
              port = colon + 1;
          }
          host = h;
      }
  }

  if (!host) {
      // error: no address configured
      pn_condition_t *cond = pn_transport_condition(transport);
      pn_condition_set_name(cond, "proton:io");
      pn_condition_set_description(cond, "Connection failed: no address configured");
      pn_transport_close_tail(transport);
      pn_transport_close_head(transport);
  } else {
      pn_socket_t sock = pn_connect(pni_reactor_io(reactor), host, port);
      // invalid sockets are ignored by poll, so we need to do this manually
      if (sock == PN_INVALID_SOCKET) {
          pn_condition_t *cond = pn_transport_condition(transport);
          pn_condition_set_name(cond, "proton:io");
          pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor)));
          pn_transport_close_tail(transport);
          pn_transport_close_head(transport);
      } else {
          pn_reactor_selectable_transport(reactor, sock, transport);
      }
  }
  pn_free(str);
}

void pni_handle_final(pn_reactor_t *reactor, pn_event_t *event) {
  assert(reactor);
  assert(event);
  pn_connection_t *conn = pn_event_connection(event);
  pn_list_remove(pn_reactor_children(reactor), conn);
}

static void pni_connection_readable(pn_selectable_t *sel)
{
  pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
  pn_transport_t *transport = pni_transport(sel);
  ssize_t capacity = pn_transport_capacity(transport);
  if (capacity > 0) {
    ssize_t n = pn_recv(pni_reactor_io(reactor), pn_selectable_get_fd(sel),
                        pn_transport_tail(transport), capacity);
    if (n <= 0) {
      if (n == 0 || !pn_wouldblock(pni_reactor_io(reactor))) {
        if (n < 0) {
          pn_condition_t *cond = pn_transport_condition(transport);
          pn_condition_set_name(cond, "proton:io");
          pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor)));
        }
        pn_transport_close_tail(transport);
      }
    } else {
      pn_transport_process(transport, (size_t)n);
    }
  }

  ssize_t newcap = pn_transport_capacity(transport);
  //occasionally transport events aren't generated when expected, so
  //the following hack ensures we always update the selector
  if (1 || newcap != capacity) {
    pni_connection_update(sel);
    pn_reactor_update(reactor, sel);
  }
}

static void pni_connection_writable(pn_selectable_t *sel)
{
  pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
  pn_transport_t *transport = pni_transport(sel);
  ssize_t pending = pn_transport_pending(transport);
  if (pending > 0) {
    ssize_t n = pn_send(pni_reactor_io(reactor), pn_selectable_get_fd(sel),
                        pn_transport_head(transport), pending);
    if (n < 0) {
      if (!pn_wouldblock(pni_reactor_io(reactor))) {
        pn_condition_t *cond = pn_transport_condition(transport);
        if (!pn_condition_is_set(cond)) {
          pn_condition_set_name(cond, "proton:io");
          pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor)));
        }
        pn_transport_close_head(transport);
      }
    } else {
      pn_transport_pop(transport, n);
    }
  }

  ssize_t newpending = pn_transport_pending(transport);
  if (newpending != pending) {
    pni_connection_update(sel);
    pn_reactor_update(reactor, sel);
  }
}

static void pni_connection_error(pn_selectable_t *sel) {
  pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
  pn_transport_t *transport = pni_transport(sel);
  pn_transport_close_head(transport);
  pn_transport_close_tail(transport);
  pn_selectable_terminate(sel);
  pn_reactor_update(reactor, sel);
}

static void pni_connection_expired(pn_selectable_t *sel) {
  pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
  pn_transport_t *transport = pni_transport(sel);
  pn_timestamp_t deadline = pn_transport_tick(transport, pn_reactor_now(reactor));
  pn_selectable_set_deadline(sel, deadline);
  ssize_t c = pni_connection_capacity(sel);
  ssize_t p = pni_connection_pending(sel);
  pn_selectable_set_reading(sel, c > 0);
  pn_selectable_set_writing(sel, p > 0);
  pn_reactor_update(reactor, sel);
}

static void pni_connection_finalize(pn_selectable_t *sel) {
  pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
  pn_transport_t *transport = pni_transport(sel);
  pn_record_t *record = pn_transport_attachments(transport);
  pn_record_set(record, PN_TRANCTX, NULL);
  pn_socket_t fd = pn_selectable_get_fd(sel);
  pn_close(pni_reactor_io(reactor), fd);
}

pn_selectable_t *pn_reactor_selectable_transport(pn_reactor_t *reactor, pn_socket_t sock, pn_transport_t *transport) {
  pn_selectable_t *sel = pn_reactor_selectable(reactor);
  pn_selectable_set_fd(sel, sock);
  pn_selectable_on_readable(sel, pni_connection_readable);
  pn_selectable_on_writable(sel, pni_connection_writable);
  pn_selectable_on_error(sel, pni_connection_error);
  pn_selectable_on_expired(sel, pni_connection_expired);
  pn_selectable_on_finalize(sel, pni_connection_finalize);
  pn_record_t *record = pn_selectable_attachments(sel);
  pn_record_def(record, PN_TRANCTX, PN_OBJECT);
  pn_record_set(record, PN_TRANCTX, transport);
  pn_record_t *tr = pn_transport_attachments(transport);
  pn_record_def(tr, PN_TRANCTX, PN_WEAKREF);
  pn_record_set(tr, PN_TRANCTX, sel);
  pni_connection_update(sel);
  pn_reactor_update(reactor, sel);
  return sel;
}

pn_connection_t *pn_reactor_connection(pn_reactor_t *reactor, pn_handler_t *handler) {
  assert(reactor);
  pn_connection_t *connection = pn_connection();
  pn_record_t *record = pn_connection_attachments(connection);
  pn_record_set_handler(record, handler);
  pn_connection_collect(connection, pn_reactor_collector(reactor));
  pn_list_add(pn_reactor_children(reactor), connection);
  pni_record_init_reactor(record, reactor);
  pn_decref(connection);
  return connection;
}

pn_connection_t *pn_reactor_connection_to_host(pn_reactor_t *reactor,
                                               const char *host,
                                               const char *port,
                                               pn_handler_t *handler) {
    pn_connection_t *connection = pn_reactor_connection(reactor, handler);
    pn_reactor_set_connection_host(reactor, connection, host, port);
    return connection;
}


void pn_reactor_set_connection_host(pn_reactor_t *reactor,
                                    pn_connection_t *connection,
                                    const char *host,
                                    const char *port)
{
    (void)reactor;  // ignored
    if (pn_connection_acceptor(connection) != NULL) {
        // this is an inbound connection created by the acceptor. The peer
        // address cannot be modified.
        return;
    }
    pni_reactor_set_connection_peer_address(connection, host, port);
}


const char *pn_reactor_get_connection_address(pn_reactor_t *reactor,
                                              pn_connection_t *connection)
{
    (void)reactor;  // ignored
    if (!connection) return NULL;
    pn_record_t *record = pn_connection_attachments(connection);
    pn_url_t *url = (pn_url_t *)pn_record_get(record, PNI_CONN_PEER_ADDRESS);
    if (url) {
        return pn_url_str(url);
    }
    return NULL;
}

#undef PN_USE_DEPRECATED_API
