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

// ScopedCallbackFactory helps in cases where you wish to allocate a Callback
// (see base/callback.h), but need to prevent any pending callbacks from
// executing when your object gets destroyed.
//
// EXAMPLE:
//
//  void GatherDataAsynchronously(Callback1<Data>::Type* callback);
//
//  class MyClass {
//   public:
//    MyClass() : factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
//    }
//
//    void Process() {
//      GatherDataAsynchronously(factory_.NewCallback(&MyClass::GotData));
//    }
//
//   private:
//    void GotData(const Data& data) {
//      ...
//    }
//
//    base::ScopedCallbackFactory<MyClass> factory_;
//  };
//
// In the above example, the Process function calls GatherDataAsynchronously to
// kick off some asynchronous processing that upon completion will notify a
// callback.  If in the meantime, the MyClass instance is destroyed, when the
// callback runs, it will notice that the MyClass instance is dead, and it will
// avoid calling the GotData method.

#ifndef BASE_SCOPED_CALLBACK_FACTORY_H_
#define BASE_SCOPED_CALLBACK_FACTORY_H_

#include "base/callback.h"
#include "base/weak_ptr.h"

namespace base {

template <class T>
class ScopedCallbackFactory {
 public:
  explicit ScopedCallbackFactory(T* obj) : weak_factory_(obj) {
  }

  typename Callback0::Type* NewCallback(
      void (T::*method)()) {
    return new CallbackImpl<void (T::*)(), Tuple0 >(
        weak_factory_.GetWeakPtr(), method);
  }

  template <typename Arg1>
  typename Callback1<Arg1>::Type* NewCallback(
      void (T::*method)(Arg1)) {
    return new CallbackImpl<void (T::*)(Arg1), Tuple1<Arg1> >(
        weak_factory_.GetWeakPtr(), method);
  }

  template <typename Arg1, typename Arg2>
  typename Callback2<Arg1, Arg2>::Type* NewCallback(
      void (T::*method)(Arg1, Arg2)) {
    return new CallbackImpl<void (T::*)(Arg1, Arg2), Tuple2<Arg1, Arg2> >(
        weak_factory_.GetWeakPtr(), method);
  }

  template <typename Arg1, typename Arg2, typename Arg3>
  typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback(
      void (T::*method)(Arg1, Arg2, Arg3)) {
    return new CallbackImpl<void (T::*)(Arg1, Arg2, Arg3),
                            Tuple3<Arg1, Arg2, Arg3> >(
        weak_factory_.GetWeakPtr(), method);
  }

  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
  typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback(
      void (T::*method)(Arg1, Arg2, Arg3, Arg4)) {
    return new CallbackImpl<void (T::*)(Arg1, Arg2, Arg3, Arg4),
                            Tuple4<Arg1, Arg2, Arg3, Arg4> >(
        weak_factory_.GetWeakPtr(), method);
  }

  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
            typename Arg5>
  typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback(
      void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) {
    return new CallbackImpl<void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5),
                            Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(
        weak_factory_.GetWeakPtr(), method);
  }

  void RevokeAll() { weak_factory_.InvalidateWeakPtrs(); }
  bool HasPendingCallbacks() const { return weak_factory_.HasWeakPtrs(); }

 private:
  template <typename Method>
  class CallbackStorage {
   public:
    CallbackStorage(const WeakPtr<T>& obj, Method meth)
        : obj_(obj),
          meth_(meth) {
    }

   protected:
    WeakPtr<T> obj_;
    Method meth_;
  };

  template <typename Method, typename Params>
  class CallbackImpl : public CallbackStorage<Method>,
                       public CallbackRunner<Params> {
   public:
    CallbackImpl(const WeakPtr<T>& obj, Method meth)
        : CallbackStorage<Method>(obj, meth) {
    }
    virtual void RunWithParams(const Params& params) {
      // Use "this->" to force C++ to look inside our templatized base class;
      // see Effective C++, 3rd Ed, item 43, p210 for details.
      if (!this->obj_)
        return;
      DispatchToMethod(this->obj_.get(), this->meth_, params);
    }
  };

  WeakPtrFactory<T> weak_factory_;
};

}  // namespace base

#endif  // BASE_SCOPED_CALLBACK_FACTORY_H_
