#include <cassert>
#include <cstddef>
#include <iostream>
#include <optional>
#include <queue>
#include <string>

class BoundedQueue {
 public:
  explicit BoundedQueue(std::size_t capacity) : capacity_(capacity) {
    assert(capacity_ > 0);
  }

  bool TryPush(std::string request) {
    if (requests_.size() >= capacity_) {
      ++rejected_;
      return false;
    }
    requests_.push(std::move(request));
    if (requests_.size() > high_watermark_) high_watermark_ = requests_.size();
    return true;
  }

  std::optional<std::string> Pop() {
    if (requests_.empty()) return std::nullopt;
    std::string request = std::move(requests_.front());
    requests_.pop();
    return request;
  }

  std::size_t rejected() const { return rejected_; }
  std::size_t high_watermark() const { return high_watermark_; }

 private:
  std::size_t capacity_;
  std::queue<std::string> requests_;
  std::size_t rejected_ = 0;
  std::size_t high_watermark_ = 0;
};

int main() {
  BoundedQueue queue(2);
  assert(queue.TryPush("r0"));
  assert(queue.TryPush("r1"));
  assert(!queue.TryPush("r2"));
  assert(queue.Pop().value() == "r0");
  assert(queue.TryPush("r3"));
  assert(queue.rejected() == 1);
  assert(queue.high_watermark() == 2);
  std::cout << "bounded_queue.cpp ok rejected=" << queue.rejected()
            << " high_watermark=" << queue.high_watermark() << '\n';
}
