/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * 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 "IOEventLoop.h"

#include <event2/event.h>
#include <fcntl.h>

#include <android-base/logging.h>

struct IOEvent {
  IOEventLoop* loop;
  event* e;
  timeval timeout;
  std::function<bool()> callback;
  bool enabled;

  IOEvent(IOEventLoop* loop, const std::function<bool()>& callback)
      : loop(loop), e(nullptr), timeout({}), callback(callback), enabled(false) {
  }

  ~IOEvent() {
    if (e != nullptr) {
      event_free(e);
    }
  }
};

IOEventLoop::IOEventLoop()
    : ebase_(nullptr), has_error_(false), use_precise_timer_(false), in_loop_(false) {}

IOEventLoop::~IOEventLoop() {
  events_.clear();
  if (ebase_ != nullptr) {
    event_base_free(ebase_);
  }
}

bool IOEventLoop::UsePreciseTimer() {
  if (ebase_ != nullptr) {
    return false;  // Too late to set the flag.
  }
  use_precise_timer_ = true;
  return true;
}

bool IOEventLoop::EnsureInit() {
  if (ebase_ == nullptr) {
    event_config* cfg = event_config_new();
    if (cfg != nullptr) {
      if (use_precise_timer_) {
        event_config_set_flag(cfg, EVENT_BASE_FLAG_PRECISE_TIMER);
      }
      if (event_config_avoid_method(cfg, "epoll") != 0) {
        LOG(ERROR) << "event_config_avoid_method";
        return false;
      }
      ebase_ = event_base_new_with_config(cfg);
      // perf event files support reporting available data via poll methods. However, it doesn't
      // work well with epoll. Because perf_poll() in kernel/events/core.c uses a report and reset
      // way to report poll events. If perf_poll() is called twice, it may return POLLIN for the
      // first time, and no events for the second time. And epoll may call perf_poll() more than
      // once to confirm events. A failed situation is below:
      // When profiling SimpleperfExampleOfKotlin on Pixel device with `-g --duration 10`, the
      // kernel fills up the buffer before we call epoll_ctl(EPOLL_CTL_ADD). Then the POLLIN event
      // is returned when calling epoll_ctl(), while no events are returned when calling
      // epoll_wait(). As a result, simpleperf doesn't receive any poll wakeup events.
      if (strcmp(event_base_get_method(ebase_), "poll") != 0) {
        LOG(ERROR) << "event_base_get_method isn't poll: " << event_base_get_method(ebase_);
        return false;
      }
      event_config_free(cfg);
    }
    if (ebase_ == nullptr) {
      LOG(ERROR) << "failed to create event_base";
      return false;
    }
  }
  return true;
}

void IOEventLoop::EventCallbackFn(int, int16_t, void* arg) {
  IOEvent* e = static_cast<IOEvent*>(arg);
  if (!e->callback()) {
    e->loop->has_error_ = true;
    e->loop->ExitLoop();
  }
}

static bool MakeFdNonBlocking(int fd) {
  int flags = fcntl(fd, F_GETFL, 0);
  if (flags == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
    PLOG(ERROR) << "fcntl() failed";
    return false;
  }
  return true;
}

IOEventRef IOEventLoop::AddReadEvent(int fd,
                                     const std::function<bool()>& callback) {
  if (!MakeFdNonBlocking(fd)) {
    return nullptr;
  }
  return AddEvent(fd, EV_READ | EV_PERSIST, nullptr, callback);
}

IOEventRef IOEventLoop::AddWriteEvent(int fd,
                                      const std::function<bool()>& callback) {
  if (!MakeFdNonBlocking(fd)) {
    return nullptr;
  }
  return AddEvent(fd, EV_WRITE | EV_PERSIST, nullptr, callback);
}

bool IOEventLoop::AddSignalEvent(int sig,
                                 const std::function<bool()>& callback) {
  return AddEvent(sig, EV_SIGNAL | EV_PERSIST, nullptr, callback) != nullptr;
}

bool IOEventLoop::AddSignalEvents(std::vector<int> sigs,
                                  const std::function<bool()>& callback) {
  for (auto sig : sigs) {
    if (!AddSignalEvent(sig, callback)) {
      return false;
    }
  }
  return true;
}

IOEventRef IOEventLoop::AddPeriodicEvent(timeval duration, const std::function<bool()>& callback) {
  return AddEvent(-1, EV_PERSIST, &duration, callback);
}

IOEventRef IOEventLoop::AddEvent(int fd_or_sig, int16_t events, timeval* timeout,
                                 const std::function<bool()>& callback) {
  if (!EnsureInit()) {
    return nullptr;
  }
  std::unique_ptr<IOEvent> e(new IOEvent(this, callback));
  e->e = event_new(ebase_, fd_or_sig, events, EventCallbackFn, e.get());
  if (e->e == nullptr) {
    LOG(ERROR) << "event_new() failed";
    return nullptr;
  }
  if (event_add(e->e, timeout) != 0) {
    LOG(ERROR) << "event_add() failed";
    return nullptr;
  }
  if (timeout != nullptr) {
    e->timeout = *timeout;
  }
  e->enabled = true;
  events_.push_back(std::move(e));
  return events_.back().get();
}

bool IOEventLoop::RunLoop() {
  in_loop_ = true;
  if (event_base_dispatch(ebase_) == -1) {
    LOG(ERROR) << "event_base_dispatch() failed";
    in_loop_ = false;
    return false;
  }
  if (has_error_) {
    return false;
  }
  return true;
}

bool IOEventLoop::ExitLoop() {
  if (in_loop_) {
    if (event_base_loopbreak(ebase_) == -1) {
      LOG(ERROR) << "event_base_loopbreak() failed";
      return false;
    }
    in_loop_ = false;
  }
  return true;
}

bool IOEventLoop::DisableEvent(IOEventRef ref) {
  if (ref->enabled) {
    if (event_del(ref->e) != 0) {
      LOG(ERROR) << "event_del() failed";
      return false;
    }
    ref->enabled = false;
  }
  return true;
}

bool IOEventLoop::EnableEvent(IOEventRef ref) {
  if (!ref->enabled) {
    timeval* timeout = (ref->timeout.tv_sec != 0 || ref->timeout.tv_usec != 0) ?
                        &ref->timeout : nullptr;
    if (event_add(ref->e, timeout) != 0) {
      LOG(ERROR) << "event_add() failed";
      return false;
    }
    ref->enabled = true;
  }
  return true;
}

bool IOEventLoop::DelEvent(IOEventRef ref) {
  DisableEvent(ref);
  IOEventLoop* loop = ref->loop;
  for (auto it = loop->events_.begin(); it != loop->events_.end(); ++it) {
    if (it->get() == ref) {
      loop->events_.erase(it);
      break;
    }
  }
  return true;
}
