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

#ifndef ENTD_SCRIPTABLE_H_
#define ENTD_SCRIPTABLE_H_

#include "base/logging.h"
#include "v8.h"

namespace entd {

// Base class for objects that are scriptable from v8.
//
// Subclasses should use a pattern like...
//
//   class Foo : public Scriptable<Foo> {
//      static const std::string class_name() { return "Foo"; }
//      ...
//   }
//
// These classes need your help to stay alive!  The lifetime of the
// reference counted scriptable object and the lifetime of the native object
// are connected.  When there are no remaining references on the script side,
// the native object will be automatically deleted.
//
// Therefore:
//   * Never pass a bare pointer to a function unless you are also maintaining
//     a reference to the v8 object.  That function might trigger a V8 garbage
//     collection which might delete the scriptable object.
//
//   * Never hold on to a bare pointer to a scriptable object for longer than
//     a function call.  It may be deleted out from under you during the next
//     V8 garbage collection cycle.
//
//   * Never allocate a scriptable object on the stack.  If they are deleted
//     while JavaScript references remain, you'll crash.
//
//   * Never use the `delete` operator on a scriptable object.  See above.
//
// You can safely hold on to a Scriptable object using a Scriptable::Reference.
// Holding one of these reference objects ensures that you have a
// v8::Persistent handle keeping your object alive.  Some examples...
//
//   // Construct a new Foo instance, and return it in a Foo::Reference which
//   // will ensure that the instance is kept alive.
//   Foo::Reference foo = Foo::New();
//
//   // If the Foo class requires some additional initialization, do it now.
//   // The -> operator works on the underlying Foo*.
//   foo->Initialize(...);
//
//   ModifyFoo(foo.native_ptr());  // Pass a bare Foo* to ModifyFoo()
//   ReadFoo(foo.native_ref());    // Pass a const Foo& to ReadFoo()
//
//   // If you have a reference already, you can use the copy constructor to
//   // make another one.
//   Foo::Reference foo_2(foo);
//
//   // You can also pass a native object to the Reference constructor to get
//   // a new reference.
//   Foo* foo_ptr = foo.native_ptr();
//   Foo::Reference foo_3(foo_ptr);
//
//   // You can get at the V8 JavaScript object associated with a native
//   // object using Foo::js_object(), as in...
//   v8::Handle<v8::Object> foo_js_obj = foo->js_object();
//
//   // The static Foo::Unwrap method will safely return the native object
//   // associated with a JavaScript object.  You should always test for
//   // a NULL result from unwrap, which indicates that the given JavaScript
//   // is not an instance of Foo.
//   foo_ptr = Foo::Unwrap(foo_js_obj);
//
// See the documentation for ::Construct() for an example of how to complete
// script-based instantiation of a Scriptable object.
//
template<typename T>
class Scriptable {
 public:

  typedef v8::Handle<v8::Value> (T::*ScriptableMethod)(
      const v8::Arguments& args);

  // Utility class to manage a reference to a Scriptable object.
  //
  // Use this class to ensure that you have a persistent handle keeping your
  // scriptable object alive.
  class Reference {
   public:
    // Construct a reference that doesn't point anywhere yet.
    Reference() { set_native_ptr(NULL); }

    // Construct from a JS Object.
    //
    // This may 'fail' if the provided value is not a JavaScript object or the
    // object is not an instance of Scriptable<T>::constructor_template.
    // Make sure to test IsEmpty() after construction.
    Reference(const v8::Handle<v8::Value>& js_object) {
      set_js_object(js_object);
    }

    // Construct from a native instance of a Scriptable<T>.
    Reference(T* native_ptr) { set_native_ptr(native_ptr); }

    // Copy constructor.
    Reference(const Reference& source) { Copy(source); }

    // Dispose of the persistent handle when the reference dies.
    ~Reference() { if (!js_object_.IsEmpty()) js_object_.Dispose(); }

    // Arrow operator gives quick access to the native pointer.
    T* operator->() const { return native_ptr_; }

    // Returns true if the reference has not been initialized.
    bool IsEmpty() const { return native_ptr_ == NULL; }

    // Copy another reference, return true if the new reference is not empty.
    bool Copy(const Reference& source) {
      set_native_ptr(source.native_ptr());
      return native_ptr_ != NULL;
    }

    // Change the referent by JavaScript value.
    //
    // Returns false if the provided value is not an object or is not
    // an instance of Scriptable<T>::constructor_template.
    //
    // Relieves the previous referent, even if the assignment fails.
    bool set_js_object(v8::Handle<v8::Value> value) {
      if (!js_object_.IsEmpty())
        js_object_.Dispose();

      native_ptr_ = T::Unwrap(value);
      if (!native_ptr_)
        return false;

      js_object_ = v8::Persistent<v8::Object>::New(native_ptr_->js_object());
      return true;
    }

    // Return the JavaScript object referred to by this reference.
    v8::Handle<v8::Object> js_object() const { return js_object_; }

    // Change the referent by native pointer, Relieving the previous referent.
    void set_native_ptr(T* native_ptr) {
      if (!js_object_.IsEmpty())
        js_object_.Dispose();

      if (native_ptr)
        js_object_ = v8::Persistent<v8::Object>::New(native_ptr->js_object());
      native_ptr_ = native_ptr;
    }

    // Return the native pointer referred to by this reference.
    T* native_ptr() const { return native_ptr_; }

    // Return a const reference to the native object referred to by this
    // reference.
    const T& native_ref() const { return *native_ptr_; }

   private:
    T* native_ptr_ ;
    v8::Persistent<v8::Object> js_object_;
  };

  // Construct a new instance of this class.
  static Scriptable<T>::Reference New();

  // Convienence function to throw an exception object with a given
  // message.
  static v8::Handle<v8::Value> ThrowException(const std::string &msg);

  // Static method to give a name to this class for debugging purposes.
  // This should be defined to return a unique name for your class, such
  // as "Foo" for a class located on the global script object, or
  // "foo.bar.AwesomeClass" for one located further down the object model.
  static const std::string class_name() { return "MISSING_CLASS_NAME"; }

  // Returns a singleton reference to the v8 function template for this class.
  // If your object is intended to be constructed from JavaScript, you
  // should connect this template to the name of your constructor function.
  // For example, to allow `var foo = new Foo()` from JavaScript...
  //
  //  class Foo : public Scriptable<Foo> { ... }
  //
  //  Context cx Context::New();
  //  Handle<Object> global = cx->Global();
  //  global->Set(String::New("Foo"), Foo::constructor_template());
  //
  // Do not override this in your subclass.  In the likely event that you
  // want to customize your constructor, override Construct() instead.
  static v8::Handle<v8::FunctionTemplate> constructor_template();

  // Initialize the constructor template for this class.
  //
  // This static method will be called once, the first time someone tries to
  // construct an instance of this class.
  //
  // If you need to perform instance specific initialization, override
  // T::Construct() instead.  See the Construct() method below for more
  // details.
  static bool InitializeTemplate(v8::Handle<v8::FunctionTemplate> ctor);

  // Bind a method of this class to a method on a Object or Function template.
  static void BindMethod(v8::Handle<v8::Template> tpl,
                         ScriptableMethod callback, const char *name);

  // Fetch the native object associated with a JS value.
  //
  // Returns NULL if the given value is not a JavaScript Object, or is not
  // an instance of the constructor_template defined by this class.
  static T* Unwrap(const v8::Handle<v8::Value>& value);

  // Same as Unwrap, except throws a JS exception on failure.
  //
  // The `desc` parameter should be a string containing additional context
  // for the exception message.  For example, if desc was "second parameter",
  // then the exception message might be "Expected object of type 'Foo':
  // second parameter"
  static T* UnwrapOrThrow(const v8::Handle<v8::Value>& value,
                          const std::string& desc);

  // Same as UnwrapOrThrow, except log a warning rather than throw an
  // exception.
  static T* UnwrapOrWarn(const v8::Handle<v8::Value>& value,
                        const std::string& desc);

  // Return true if the given JavaScript value represents an instance of
  // this class.
  static bool IsInstance(const v8::Handle<v8::Value>& value) {
    return Unwrap(value) != NULL;
  }

  // Return the JavaScript object for this instance.
  virtual v8::Handle<v8::Object> js_object() const { return js_object_; }

  // Keep track of the number of instances of this class that are currently
  // alive.
  //
  // This is here to help detect leaks that can happen when these objects are
  // improperly handled.  This method is exposed to script as the
  // 'instanceCount' property of the constructor function.
  //
  // Pass +1 to increment the count, -1 to decrement, and 0 to read.  But
  // only if you know what you're doing.
  static int InstanceCount(int delta) {
    static int i = 0;
    return i += delta;
  }

  // Associate this instance with a given JavaScript Object.
  //
  // You should not have to call this function directly.  Leave the
  // details to T::New() or Scriptable::Construct() deal with it.
  //
  // Returns false if the the js_object is not an instance of the
  // constructor_template defined by this class, or if the instance has
  // already been associated with a JavaScript object.
  virtual bool set_js_object(v8::Handle<v8::Object> js_object);

 protected:
  // Complete the construction of a new instance of this class from JavaScript.
  //
  // This method is NOT called if you construct an instance from native code.
  // Override this if you need to parse constructor arguments, and make sure to
  // call any class specific initialization function, passing it any arguments
  // you may have parsed.
  //
  // You can abort the constructor by throwing a v8 exception and returning
  // any value.
  //
  // Your custom Construct method might look something like...
  //
  // Handle<Value> Foo::Construct(const Arguments& args) {
  //   if (args.Length > 0) {
  //     // Throw an exception and return Undefined() if things don't go
  //     // well.
  //     return ThrowException("Expected no arguments");
  //   }
  //
  //   // Perform some Foo specific initialization...
  //   Initialize(...);
  //
  //   // Make sure to return the new instance on success...
  //   return value;
  // }
  //
  v8::Handle<v8::Value> Construct(const v8::Arguments& args) {
    return args.This();
  };

  // Set up the construction of a new instance of this class from native code.
  //
  // We don't want the script constructor running when we construct from
  // native code.  The script constructor takes its arguments from script,
  // so we'd have to convert everything into v8::Values, so that the
  // native code on the other end could unwrap it.  Instead, when constructing
  // from native code, we change the constructor's InvocationCallback from
  // ScriptConstruct to NativeConstruct.  NativeConstruct just returns
  // args.This() object without creating a new native object or
  // calling T::Construct().
  //
  // You won't need to override this since it's only used to prevent the
  // normal ScriptConstruct from happening, when constructing from native
  // code.
  static v8::Handle<v8::Value> NativeConstruct(const v8::Arguments& args);

  // Set up the construction of a new instance of this class from JavaScript.
  //
  // This ensures that the constructor was called with the JavaScript 'new'
  // operator, and associates the new JavaScript object with a fresh native
  // instance of this class.  Once that's done, it calls T::Construct(args)
  // to perform any class specific initiation, and returns whatever
  // T::Construct returns.
  //
  // You won't need to override this unless you run into a case where you want
  // the constructor to also be callable as a normal function, without 'new'.
  //
  // This is hooked up to the InvocationCallback of T::constructor_template
  // by default.
  static v8::Handle<v8::Value> ScriptConstruct(const v8::Arguments& args);

  // Called when the internal weak reference to the JavaScript face of this
  // object has indicated there are no more references.  This will delete
  // the native instance.
  static void Harakiri(v8::Persistent<v8::Value> object, void* parameter) {
    T* instance = Unwrap(object);
    delete instance;
  }

  // Call this from your overridden Construct() method if you don't want
  // script to be able to invoke your constructor.
  static v8::Handle<v8::Value> ThrowNoScriptableConstructor() {
    return ThrowException(class_name() + "() cannot be invoked from script");
  }

  Scriptable() { Scriptable<T>::InstanceCount(+1); }
  virtual ~Scriptable() { Scriptable<T>::InstanceCount(-1); }

 private:
  // Functioniod class to thunk from a static v8::InvocationCallback to a
  // method of T.  Used by T::BindMethod.
  class Dispatcher {
   public:
    Dispatcher(ScriptableMethod callback) : callback_(callback) {}

    // Standard static v8::InvocationCallback which dispatches to a method
    // on an instance of T.
    static v8::Handle<v8::Value> Callback(const v8::Arguments& args) {
      T* native_ptr = T::UnwrapOrThrow(args.This(), "this");
      if (!native_ptr)
        return v8::Undefined();

      Dispatcher* dispatcher = reinterpret_cast<Dispatcher*>(
          v8::External::Unwrap(args.Data()));

      if (!dispatcher) {
        return T::ThrowException("Unexpected error unwrapping "
                                 "dispatcher object");
      }

      // Ok, so, all of the boilerplate ugliness that this class is intended
      // to save gets wrung out of the client code and collects here, in this
      // funky line of code.  All it's doing is applying the
      // dispatcher->callback_ method to the object pointed to by native_ptr.
      // C++ makes us feel bad about it by making it ugly, but it's worth
      // the guilt.
      return ((*native_ptr).*(dispatcher->callback_))(args);
    }

   private:
    ScriptableMethod callback_;
  };

  // Reference to the JavaScript notion of this instance.  This is a weak
  // reference and will not partake in keeping this object alive.
  v8::Persistent<v8::Object> js_object_;

  // This is hooked up to the constructor in JavaScript as Foo.instanceCount,
  // so that testcases can detect leaks.
  static v8::Handle<v8::Value> GetInstanceCount(v8::Local<v8::String> name,
                                                const v8::AccessorInfo& info) {
    return v8::Integer::New(Scriptable<T>::InstanceCount(0));
  }

  DISALLOW_COPY_AND_ASSIGN(Scriptable<T>);
};

}  // namespace entd

#include "scriptable-inl.h"

#endif  // ENTD_SCRIPTABLE_H_
