// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#pragma once

#include <stdint.h>
#include <limits>
#include <ostream>
#include <type_traits>
#include "callback.h"
#include "optional.h"

#include <iostream>

namespace overnet {

// Number of microseconds per millisecond.
static const uint64_t kUsPerMs = 1000;
static const uint64_t kUsPerSec = 1000000;

class TimeDelta {
 public:
  static constexpr TimeDelta PositiveInf() {
    return TimeDelta(std::numeric_limits<int64_t>::max());
  }
  static constexpr TimeDelta NegativeInf() {
    return TimeDelta(std::numeric_limits<int64_t>::min());
  }
  static constexpr TimeDelta Zero() { return TimeDelta(0); }
  static constexpr TimeDelta FromMicroseconds(int64_t delta) {
    return TimeDelta(delta);
  }
  static constexpr TimeDelta FromMilliseconds(int64_t delta) {
    return TimeDelta(delta * kUsPerMs);
  }
  static constexpr TimeDelta FromSeconds(int64_t delta) {
    return TimeDelta(delta * kUsPerSec);
  }
  static constexpr TimeDelta FromMinutes(int64_t delta) {
    return FromSeconds(delta * 60);
  }
  static constexpr TimeDelta FromHours(int64_t delta) {
    return FromMinutes(delta * 60);
  }

  constexpr int64_t as_us() const { return delta_; }

 private:
  explicit constexpr TimeDelta(int64_t delta) : delta_(delta) {}
  int64_t delta_;
};

class TimeStamp {
 public:
  static constexpr TimeStamp Epoch() { return TimeStamp(TimeDelta::Zero()); }
  static constexpr TimeStamp AfterEpoch(TimeDelta td) { return TimeStamp(td); }

  constexpr TimeDelta after_epoch() const { return td_; }

 private:
  explicit constexpr TimeStamp(TimeDelta td) : td_(td) {}

  TimeDelta td_;
};

inline constexpr bool operator==(TimeDelta a, TimeDelta b) {
  return a.as_us() == b.as_us();
}

inline constexpr bool operator!=(TimeDelta a, TimeDelta b) {
  return a.as_us() != b.as_us();
}

inline std::ostream& operator<<(std::ostream& out, TimeDelta a) {
  if (a == TimeDelta::PositiveInf())
    return out << "+inf";
  if (a == TimeDelta::NegativeInf())
    return out << "-inf";
  auto us = a.as_us();
  if (us > -1000 && us < 1000)
    return out << us << "us";
  if (us > -1000000 && us < 1000000)
    return out << (us / 1000.0) << "ms";
  return out << (us / 1000000.0) << "s";
}

inline std::ostream& operator<<(std::ostream& out, TimeStamp ts) {
  return out << '@' << ts.after_epoch();
}

inline constexpr TimeDelta operator+(TimeDelta a, TimeDelta b) {
  if (a == TimeDelta::PositiveInf() || a == TimeDelta::NegativeInf() ||
      b == TimeDelta::Zero()) {
    return a;
  }
  if (b == TimeDelta::PositiveInf())
    return b;
  if (b == TimeDelta::NegativeInf())
    return b;
  if (b.as_us() > 0) {
    if (a.as_us() > 0 &&
        b.as_us() > TimeDelta::PositiveInf().as_us() - a.as_us()) {
      return TimeDelta::PositiveInf();
    }
  } else {
    if (a.as_us() < 0 &&
        b.as_us() < TimeDelta::NegativeInf().as_us() - a.as_us()) {
      return TimeDelta::NegativeInf();
    }
  }
  return TimeDelta::FromMicroseconds(a.as_us() + b.as_us());
}

inline constexpr TimeDelta operator-(TimeDelta x) {
  if (x == TimeDelta::NegativeInf())
    return TimeDelta::PositiveInf();
  if (x == TimeDelta::PositiveInf())
    return TimeDelta::NegativeInf();
  return TimeDelta::FromMicroseconds(-x.as_us());
}

inline constexpr TimeDelta operator-(TimeDelta a, TimeDelta b) {
  return a + (-b);
}

inline constexpr bool operator>(TimeDelta a, TimeDelta b) {
  return a.as_us() > b.as_us();
}

inline constexpr bool operator<(TimeDelta a, TimeDelta b) {
  return a.as_us() < b.as_us();
}

inline constexpr bool operator>=(TimeDelta a, TimeDelta b) {
  return a.as_us() >= b.as_us();
}

inline constexpr bool operator<=(TimeDelta a, TimeDelta b) {
  return a.as_us() <= b.as_us();
}

inline constexpr TimeDelta operator-(TimeStamp a, TimeStamp b) {
  return a.after_epoch() - b.after_epoch();
}

inline constexpr TimeStamp operator+(TimeStamp a, TimeDelta b) {
  return TimeStamp::AfterEpoch(a.after_epoch() + b);
}

inline constexpr TimeDelta operator*(int multiplier, TimeDelta x) {
  if (multiplier == 0)
    return TimeDelta::Zero();
  bool neg = false;
  if (multiplier < 0) {
    neg = true;
    multiplier = -multiplier;
  }
  TimeDelta r = x;
  for (int i = 1; i < multiplier; i++) {
    r = r + x;
  }
  if (neg) {
    return -r;
  } else {
    return r;
  }
}

inline constexpr TimeDelta operator/(TimeDelta x, int divisor) {
  if (divisor == 0) {
    if (x.as_us() < 0) {
      return TimeDelta::NegativeInf();
    } else {
      return TimeDelta::PositiveInf();
    }
  }
  if (x == TimeDelta::NegativeInf()) {
    return TimeDelta::NegativeInf();
  }
  if (x == TimeDelta::PositiveInf()) {
    return TimeDelta::PositiveInf();
  }
  return TimeDelta::FromMicroseconds(x.as_us() / divisor);
}

inline constexpr bool operator>(TimeStamp a, TimeStamp b) {
  return a.after_epoch() > b.after_epoch();
}

inline constexpr bool operator<(TimeStamp a, TimeStamp b) {
  return a.after_epoch() < b.after_epoch();
}

inline constexpr bool operator>=(TimeStamp a, TimeStamp b) {
  return a.after_epoch() >= b.after_epoch();
}

inline constexpr bool operator<=(TimeStamp a, TimeStamp b) {
  return a.after_epoch() <= b.after_epoch();
}

inline constexpr bool operator==(TimeStamp a, TimeStamp b) {
  return a.after_epoch() == b.after_epoch();
}

inline constexpr bool operator!=(TimeStamp a, TimeStamp b) {
  return a.after_epoch() != b.after_epoch();
}

class Timeout;

class Timer {
  friend class Timeout;

 public:
  virtual TimeStamp Now() = 0;

  template <class F>
  void At(TimeStamp t, F f);
  void At(TimeStamp t, StatusCallback cb);

 protected:
  template <class T>
  T* TimeoutStorage(Timeout* timeout);

  static void FireTimeout(Timeout* timeout, Status status);

 private:
  virtual void InitTimeout(Timeout* timeout, TimeStamp when) = 0;
  virtual void CancelTimeout(Timeout* timeout, Status status) = 0;
};

class Timeout {
  friend class Timer;

 public:
  static constexpr uint64_t kMaxTimerStorage = 5 * sizeof(void*);

  Timeout(const Timeout&) = delete;
  Timeout& operator=(const Timeout&) = delete;

  // Initialize a timeout for timestamp when. cb will be called when the timeout
  // expires (with status OK) or when the timeout is cancelled (with non-OK
  // status).
  Timeout(Timer* timer, TimeStamp when, StatusCallback cb)
      : timer_(timer), cb_(std::move(cb)) {
    assert(!cb_.empty());
    timer_->InitTimeout(this, when);
  }

  ~Timeout() {
#ifndef NDEBUG
    assert(!destroyed_);
    destroyed_ = true;
#endif
    if (!cb_.empty())
      Cancel();
    assert(cb_.empty());
  }

  void Cancel(Status status = Status::Cancelled()) {
    timer_->CancelTimeout(this, std::move(status));
  }

 private:
#ifndef NDEBUG
  bool destroyed_ = false;
#endif
  Timer* const timer_;
  StatusCallback cb_;
  typename std::aligned_storage<kMaxTimerStorage>::type storage_;
};

template <class T>
T* Timer::TimeoutStorage(Timeout* timeout) {
  static_assert(Timeout::kMaxTimerStorage >= sizeof(T),
                "Must have enough storage in Timeout for Timer data");
  return reinterpret_cast<T*>(&timeout->storage_);
}

inline void Timer::FireTimeout(Timeout* timeout, Status status) {
  if (timeout->cb_.empty())
    return;
  auto cb = std::move(timeout->cb_);
  cb(status);
}

template <class F>
void Timer::At(TimeStamp t, F f) {
  At(t, StatusCallback(ALLOCATED_CALLBACK,
                       [f = std::move(f)](const Status& status) mutable {
                         if (status.is_ok()) {
                           f();
                         }
                       }));
}

}  // namespace overnet
