// 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 <stdlib.h>
#include <string.h>
#include <memory>
#include "src/connectivity/overnet/lib/vocabulary/status.h"

namespace overnet {

// Completion callback function: a move-only functor that ensures that the
// underlying callback is called once and only once

enum AllocatedCallback { ALLOCATED_CALLBACK };

template <class Arg, size_t kMaxPayload = sizeof(void*)>
class Callback {
 public:
  // Use a (manually constructed) vtable to encode what to do when a callback is
  // made (or not)
  // This has been observed to generate more efficient code than writing out a
  // C++ style vtable
  struct VTable {
    void (*move)(void* dst, void* src);
    void (*call)(void* env, Arg&& arg);
    void (*not_called)(void* env);
  };

  Callback() : vtable_(&null_vtable) {}
  ~Callback() { vtable_->not_called(&env_); }

  template <class F,
            typename = typename std::enable_if<sizeof(F) <= kMaxPayload>::type>
  Callback(F&& f) {
    vtable_ = &SmallFunctor<F>::vtable;
    SmallFunctor<F>::InitEnv(&env_, std::forward<F>(f));
  }

  template <class F>
  Callback(AllocatedCallback, F&& f)
      : Callback([pf = new F(std::forward<F>(f))](Arg&& arg) {
          auto fn = pf;
          (*fn)(std::forward<Arg>(arg));
          delete fn;
        }){};

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

  Callback(Callback&& other) {
    vtable_ = other.vtable_;
    other.vtable_ = &null_vtable;
    vtable_->move(&env_, &other.env_);
  }

  Callback& operator=(Callback&& other) {
    vtable_->not_called(&env_);
    vtable_ = other.vtable_;
    other.vtable_ = &null_vtable;
    vtable_->move(&env_, &other.env_);
    return *this;
  }

  void operator()(Arg arg) {
    const auto* const vtable = vtable_;
    vtable_ = &null_vtable;
    vtable->call(&env_, std::forward<Arg>(arg));
  }

  bool empty() const { return vtable_ == &null_vtable; }

  static Callback Ignored() {
    return [](const Arg&) {};
  }

  static Callback Unimplemented() {
    return [](const Arg&) { abort(); };
  }

  static Callback MustSucceed() {
    return [](const Arg& arg) { assert(arg.is_ok()); };
  }

 private:
  static void NullVTableMove(void*, void*) {}
  static void NullVTableNotCalled(void*) {}
  static void NullVTableCall(void*, Arg&&) { abort(); }

  static const VTable null_vtable;

  template <class F>
  class SmallFunctor {
   public:
    static const VTable vtable;
    static void InitEnv(void* env, F&& f) { new (env) F(std::forward<F>(f)); }

   private:
    static void Move(void* dst, void* src) {
      F* f = static_cast<F*>(src);
      new (dst) F(std::move(*f));
      f->~F();
    }
    static void Call(void* env, Arg&& arg) {
      F* f = static_cast<F*>(env);
      (*f)(std::forward<Arg>(arg));
      f->~F();
    }
    static void NotCalled(void* env) {
      Call(env, Arg(StatusCode::CANCELLED, __PRETTY_FUNCTION__));
    }
  };

  const VTable* vtable_;
  typename std::aligned_storage<kMaxPayload>::type env_;
};

typedef Callback<Status> StatusCallback;
template <class T>
using StatusOrCallback = Callback<StatusOr<T>>;

template <class Arg, size_t kMaxPayload>
const typename Callback<Arg, kMaxPayload>::VTable
    Callback<Arg, kMaxPayload>::null_vtable = {NullVTableMove, NullVTableCall,
                                               NullVTableNotCalled};

template <class Arg, size_t kMaxPayload>
template <class F>
const typename Callback<Arg, kMaxPayload>::VTable
    Callback<Arg, kMaxPayload>::SmallFunctor<F>::vtable = {Move, Call,
                                                           NotCalled};

template <size_t kMaxPayload>
class Callback<void, kMaxPayload> {
 public:
  // Use a (manually constructed) vtable to encode what to do when a callback is
  // made (or not)
  // This has been observed to generate more efficient code than writing out a
  // C++ style vtable
  struct VTable {
    void (*move)(void* dst, void* src);
    void (*call)(void* env);
    void (*not_called)(void* env);
  };

  Callback() : vtable_(&null_vtable) {}
  ~Callback() { vtable_->not_called(&env_); }

  template <class F,
            typename = typename std::enable_if<sizeof(F) <= kMaxPayload>::type>
  Callback(F&& f) {
    vtable_ = &SmallFunctor<F>::vtable;
    SmallFunctor<F>::InitEnv(&env_, std::forward<F>(f));
  }

  template <class F>
  Callback(AllocatedCallback, F&& f)
      : Callback([pf = new F(std::forward<F>(f))]() {
          (*pf)();
          delete pf;
        }){};

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

  Callback(Callback&& other) {
    vtable_ = other.vtable_;
    other.vtable_ = &null_vtable;
    vtable_->move(&env_, &other.env_);
  }

  Callback& operator=(Callback&& other) {
    vtable_->not_called(&env_);
    vtable_ = other.vtable_;
    other.vtable_ = &null_vtable;
    vtable_->move(&env_, &other.env_);
    return *this;
  }

  void operator()() {
    const auto* const vtable = vtable_;
    vtable_ = &null_vtable;
    vtable->call(&env_);
  }

  bool empty() const { return vtable_ == &null_vtable; }

  static Callback Ignored() {
    return []() {};
  }

  static Callback Unimplemented() {
    return []() { abort(); };
  }

 private:
  static void NullVTableMove(void*, void*) {}
  static void NullVTableNotCalled(void*) {}
  static void NullVTableCall(void*) { abort(); }

  static const VTable null_vtable;

  template <class F>
  class SmallFunctor {
   public:
    static const VTable vtable;
    static void InitEnv(void* env, F&& f) { new (env) F(std::forward<F>(f)); }

   private:
    static void Move(void* dst, void* src) {
      F* f = static_cast<F*>(src);
      new (dst) F(std::move(*f));
      f->~F();
    }
    static void Call(void* env) {
      F* f = static_cast<F*>(env);
      (*f)();
      f->~F();
    }
    static void NotCalled(void* env) { Call(env); }
  };

  const VTable* vtable_;
  typename std::aligned_storage<kMaxPayload>::type env_;
};

template <size_t kMaxPayload>
const typename Callback<void, kMaxPayload>::VTable
    Callback<void, kMaxPayload>::null_vtable = {NullVTableMove, NullVTableCall,
                                                NullVTableNotCalled};

template <size_t kMaxPayload>
template <class F>
const typename Callback<void, kMaxPayload>::VTable
    Callback<void, kMaxPayload>::SmallFunctor<F>::vtable = {Move, Call,
                                                            NotCalled};

}  // namespace overnet
