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

#include <proton/selector.h>
#include <proton/error.h>
#include <poll.h>
#include <stdlib.h>
#include <assert.h>
#include "platform.h"
#include "selectable.h"
#include "util.h"

struct pn_selector_t {
  struct pollfd *fds;
  pn_timestamp_t *deadlines;
  size_t capacity;
  pn_list_t *selectables;
  size_t current;
  pn_timestamp_t awoken;
  pn_error_t *error;
};

void pn_selector_initialize(void *obj)
{
  pn_selector_t *selector = (pn_selector_t *) obj;
  selector->fds = NULL;
  selector->deadlines = NULL;
  selector->capacity = 0;
  selector->selectables = pn_list(PN_WEAKREF, 0);
  selector->current = 0;
  selector->awoken = 0;
  selector->error = pn_error();
}

void pn_selector_finalize(void *obj)
{
  pn_selector_t *selector = (pn_selector_t *) obj;
  free(selector->fds);
  free(selector->deadlines);
  pn_free(selector->selectables);
  pn_error_free(selector->error);
}

#define pn_selector_hashcode NULL
#define pn_selector_compare NULL
#define pn_selector_inspect NULL

pn_selector_t *pni_selector(void)
{
  static const pn_class_t clazz = PN_CLASS(pn_selector);
  pn_selector_t *selector = (pn_selector_t *) pn_class_new(&clazz, sizeof(pn_selector_t));
  return selector;
}

void pn_selector_add(pn_selector_t *selector, pn_selectable_t *selectable)
{
  assert(selector);
  assert(selectable);
  assert(pni_selectable_get_index(selectable) < 0);

  if (pni_selectable_get_index(selectable) < 0) {
    pn_list_add(selector->selectables, selectable);
    size_t size = pn_list_size(selector->selectables);

    if (selector->capacity < size) {
      selector->fds = (struct pollfd *) realloc(selector->fds, size*sizeof(struct pollfd));
      selector->deadlines = (pn_timestamp_t *) realloc(selector->deadlines, size*sizeof(pn_timestamp_t));
      selector->capacity = size;
    }

    pni_selectable_set_index(selectable, size - 1);
  }

  pn_selector_update(selector, selectable);
}

void pn_selector_update(pn_selector_t *selector, pn_selectable_t *selectable)
{
  int idx = pni_selectable_get_index(selectable);
  assert(idx >= 0);
  selector->fds[idx].fd = pn_selectable_get_fd(selectable);
  selector->fds[idx].events = 0;
  selector->fds[idx].revents = 0;
  if (pn_selectable_is_reading(selectable)) {
    selector->fds[idx].events |= POLLIN;
  }
  if (pn_selectable_is_writing(selectable)) {
    selector->fds[idx].events |= POLLOUT;
  }
  selector->deadlines[idx] = pn_selectable_get_deadline(selectable);
}

void pn_selector_remove(pn_selector_t *selector, pn_selectable_t *selectable)
{
  assert(selector);
  assert(selectable);

  int idx = pni_selectable_get_index(selectable);
  assert(idx >= 0);
  pn_list_del(selector->selectables, idx, 1);
  size_t size = pn_list_size(selector->selectables);
  for (size_t i = idx; i < size; i++) {
    pn_selectable_t *sel = (pn_selectable_t *) pn_list_get(selector->selectables, i);
    pni_selectable_set_index(sel, i);
    selector->fds[i] = selector->fds[i + 1];
  }

  pni_selectable_set_index(selectable, -1);

  if (selector->current >= (size_t) idx) {
    selector->current--;
  }
}

size_t pn_selector_size(pn_selector_t *selector) {
  assert(selector);
  return pn_list_size(selector->selectables);
}

int pn_selector_select(pn_selector_t *selector, int timeout)
{
  assert(selector);

  size_t size = pn_list_size(selector->selectables);

  if (timeout) {
    pn_timestamp_t deadline = 0;
    for (size_t i = 0; i < size; i++) {
      pn_timestamp_t d = selector->deadlines[i];
      if (d)
        deadline = (deadline == 0) ? d : pn_min(deadline, d);
    }

    if (deadline) {
      pn_timestamp_t now = pn_i_now();
      int64_t delta = deadline - now;
      if (delta < 0) {
        timeout = 0;
      } else if (delta < timeout) {
        timeout = delta;
      }
    }
  }

  int error = 0;
  int result = poll(selector->fds, size, timeout);
  if (result == -1) {
    error = pn_i_error_from_errno(selector->error, "poll");
  } else {
    selector->current = 0;
    selector->awoken = pn_i_now();
  }

  return error;
}

pn_selectable_t *pn_selector_next(pn_selector_t *selector, int *events)
{
  pn_list_t *l = selector->selectables;
  size_t size = pn_list_size(l);
  while (selector->current < size) {
    pn_selectable_t *sel = (pn_selectable_t *) pn_list_get(l, selector->current);
    struct pollfd *pfd = &selector->fds[selector->current];
    pn_timestamp_t deadline = selector->deadlines[selector->current];
    int ev = 0;
    if (pfd->revents & POLLIN) {
      ev |= PN_READABLE;
    }
    if ((pfd->revents & POLLERR) ||
        (pfd->revents & POLLHUP) ||
        (pfd->revents & POLLNVAL)) {
      ev |= PN_ERROR;
    }
    if (pfd->revents & POLLOUT) {
      ev |= PN_WRITABLE;
    }
    if (deadline && selector->awoken >= deadline) {
      ev |= PN_EXPIRED;
    }
    selector->current++;
    if (ev) {
      *events = ev;
      return sel;
    }
  }
  return NULL;
}

void pn_selector_free(pn_selector_t *selector)
{
  assert(selector);
  pn_free(selector);
}
