// Copyright 2019 The Marl Authors.
//
// 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
//
//     https://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 marl_event_h
#define marl_event_h

#include "conditionvariable.h"
#include "containers.h"
#include "memory.h"

#include <chrono>

namespace marl {

// Event is a synchronization primitive used to block until a signal is raised.
class Event {
 public:
  enum class Mode : uint8_t {
    // The event signal will be automatically reset when a call to wait()
    // returns.
    // A single call to signal() will only unblock a single (possibly
    // future) call to wait().
    Auto,

    // While the event is in the signaled state, any calls to wait() will
    // unblock without automatically reseting the signaled state.
    // The signaled state can be reset with a call to clear().
    Manual
  };

  inline Event(Mode mode = Mode::Auto,
               bool initialState = false,
               Allocator* allocator = Allocator::Default);

  // signal() signals the event, possibly unblocking a call to wait().
  inline void signal() const;

  // clear() clears the signaled state.
  inline void clear() const;

  // wait() blocks until the event is signaled.
  // If the event was constructed with the Auto Mode, then only one
  // call to wait() will unblock before returning, upon which the signalled
  // state will be automatically cleared.
  inline void wait() const;

  // wait_for() blocks until the event is signaled, or the timeout has been
  // reached.
  // If the timeout was reached, then wait_for() return false.
  // If the event is signalled and event was constructed with the Auto Mode,
  // then only one call to wait() will unblock before returning, upon which the
  // signalled state will be automatically cleared.
  template <typename Rep, typename Period>
  inline bool wait_for(
      const std::chrono::duration<Rep, Period>& duration) const;

  // wait_until() blocks until the event is signaled, or the timeout has been
  // reached.
  // If the timeout was reached, then wait_for() return false.
  // If the event is signalled and event was constructed with the Auto Mode,
  // then only one call to wait() will unblock before returning, upon which the
  // signalled state will be automatically cleared.
  template <typename Clock, typename Duration>
  inline bool wait_until(
      const std::chrono::time_point<Clock, Duration>& timeout) const;

  // test() returns true if the event is signaled, otherwise false.
  // If the event is signalled and was constructed with the Auto Mode
  // then the signalled state will be automatically cleared upon returning.
  inline bool test() const;

  // isSignalled() returns true if the event is signaled, otherwise false.
  // Unlike test() the signal is not automatically cleared when the event was
  // constructed with the Auto Mode.
  // Note: No lock is held after bool() returns, so the event state may
  // immediately change after returning. Use with caution.
  inline bool isSignalled() const;

  // any returns an event that is automatically signalled whenever any of the
  // events in the list are signalled.
  template <typename Iterator>
  inline static Event any(Mode mode,
                          const Iterator& begin,
                          const Iterator& end);

  // any returns an event that is automatically signalled whenever any of the
  // events in the list are signalled.
  // This overload defaults to using the Auto mode.
  template <typename Iterator>
  inline static Event any(const Iterator& begin, const Iterator& end);

 private:
  struct Shared {
    inline Shared(Allocator* allocator, Mode mode, bool initialState);
    inline void signal();
    inline void wait();

    template <typename Rep, typename Period>
    inline bool wait_for(const std::chrono::duration<Rep, Period>& duration);

    template <typename Clock, typename Duration>
    inline bool wait_until(
        const std::chrono::time_point<Clock, Duration>& timeout);

    marl::mutex mutex;
    ConditionVariable cv;
    containers::vector<std::shared_ptr<Shared>, 1> deps;
    const Mode mode;
    bool signalled;
  };

  const std::shared_ptr<Shared> shared;
};

Event::Shared::Shared(Allocator* allocator, Mode mode, bool initialState)
    : cv(allocator), mode(mode), signalled(initialState) {}

void Event::Shared::signal() {
  marl::lock lock(mutex);
  if (signalled) {
    return;
  }
  signalled = true;
  if (mode == Mode::Auto) {
    cv.notify_one();
  } else {
    cv.notify_all();
  }
  for (auto dep : deps) {
    dep->signal();
  }
}

void Event::Shared::wait() {
  marl::lock lock(mutex);
  cv.wait(lock, [&] { return signalled; });
  if (mode == Mode::Auto) {
    signalled = false;
  }
}

template <typename Rep, typename Period>
bool Event::Shared::wait_for(
    const std::chrono::duration<Rep, Period>& duration) {
  marl::lock lock(mutex);
  if (!cv.wait_for(lock, duration, [&] { return signalled; })) {
    return false;
  }
  if (mode == Mode::Auto) {
    signalled = false;
  }
  return true;
}

template <typename Clock, typename Duration>
bool Event::Shared::wait_until(
    const std::chrono::time_point<Clock, Duration>& timeout) {
  marl::lock lock(mutex);
  if (!cv.wait_until(lock, timeout, [&] { return signalled; })) {
    return false;
  }
  if (mode == Mode::Auto) {
    signalled = false;
  }
  return true;
}

Event::Event(Mode mode /* = Mode::Auto */,
             bool initialState /* = false */,
             Allocator* allocator /* = Allocator::Default */)
    : shared(allocator->make_shared<Shared>(allocator, mode, initialState)) {}

void Event::signal() const {
  shared->signal();
}

void Event::clear() const {
  marl::lock lock(shared->mutex);
  shared->signalled = false;
}

void Event::wait() const {
  shared->wait();
}

template <typename Rep, typename Period>
bool Event::wait_for(const std::chrono::duration<Rep, Period>& duration) const {
  return shared->wait_for(duration);
}

template <typename Clock, typename Duration>
bool Event::wait_until(
    const std::chrono::time_point<Clock, Duration>& timeout) const {
  return shared->wait_until(timeout);
}

bool Event::test() const {
  marl::lock lock(shared->mutex);
  if (!shared->signalled) {
    return false;
  }
  if (shared->mode == Mode::Auto) {
    shared->signalled = false;
  }
  return true;
}

bool Event::isSignalled() const {
  marl::lock lock(shared->mutex);
  return shared->signalled;
}

template <typename Iterator>
Event Event::any(Mode mode, const Iterator& begin, const Iterator& end) {
  Event any(mode, false);
  for (auto it = begin; it != end; it++) {
    auto s = it->shared;
    marl::lock lock(s->mutex);
    if (s->signalled) {
      any.signal();
    }
    s->deps.push_back(any.shared);
  }
  return any;
}

template <typename Iterator>
Event Event::any(const Iterator& begin, const Iterator& end) {
  return any(Mode::Auto, begin, end);
}

}  // namespace marl

#endif  // marl_event_h
