/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef COBALT_SCRIPT_SCRIPT_VALUE_H_
#define COBALT_SCRIPT_SCRIPT_VALUE_H_

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"

namespace cobalt {
namespace script {

class Wrappable;

// ScriptValue is a wrapper around raw JavaScript values that are being passed
// into Cobalt. These are values that do not correspond to Cobalt Wrappable
// objects. Specifically, this could include objects that implement the
// EventListener interface, callback functions, promises, or any Javascript
// value at all.  As long as Cobalt maintains a handle to such an value, it
// should not be garbage collected, if it is a garbage-collectible thing (GC
// thing). Web API implementations should hold on to a reference to a
// ScriptValue implementation by constructing a ScriptValue::Reference object.
//
// The Reference class takes as a constructor parameter a pointer to the
// Wrappable that is holding onto the ScriptValue. This ensures that the
// JavaScript engine's garbage collection is aware of the relationship between
// the ScriptValue and the Wrappable's corresponding JavaScript wrapper. This
// will ensure that the garbage collector can detect when these values are
// detached from the rest of the graph of JavaScript GC things, and can safely
// be garbage collected.
template <class T>
class ScriptValue {
 public:
  // The Reference class maintains the ownership relationship between a
  // Wrappable and the JavaScript value wrapped by a ScriptValue. This is an
  // RAII object in that creation of a Reference instance will mark the
  // underlying value as owned by this wrappable, and the underlying object will
  // be unmarked when this Reference is destructed.  The lifetime of a Reference
  // must be at least as long as the Wrappable that has been passed into the
  // constructor.
  class Reference {
   public:
    Reference(Wrappable* wrappable, scoped_ptr<ScriptValue> script_value)
        : owner_(wrappable), referenced_value_(script_value.Pass()) {
      DCHECK(referenced_value_);
      referenced_value_->RegisterOwner(owner_);
    }

    Reference(Wrappable* wrappable, const ScriptValue& script_value)
        : owner_(wrappable), referenced_value_(script_value.MakeCopy()) {
      DCHECK(referenced_value_);
      referenced_value_->RegisterOwner(owner_);
    }

    const T& value() const { return *(referenced_value_->GetScriptValue()); }

    // Return the referenced ScriptValue. This ScriptValue can
    // be passed back into the JavaScript bindings layer where the referenced
    // JavaScript object can be extracted from the ScriptValue.
    const ScriptValue<T>& referenced_value() const {
      return *(referenced_value_.get());
    }

    ~Reference() { referenced_value_->DeregisterOwner(owner_); }

   private:
    Wrappable* const owner_;
    scoped_ptr<ScriptValue> referenced_value_;

    DISALLOW_COPY_AND_ASSIGN(Reference);
  };

  // Prevent garbage collection of the ScriptValue. This should be used with
  // care as it can result in resource leaks if not managed appropriately.
  // A common use case is to create a StrongReference on the stack when a
  // ScriptValue is passed into a function, but a reference to the ScriptValue
  // doesn't need to be retained past the scope of the function.
  class StrongReference {
   public:
    explicit StrongReference(scoped_ptr<ScriptValue> script_value)
        : referenced_value_(script_value.Pass()) {
      DCHECK(referenced_value_);
      referenced_value_->PreventGarbageCollection();
    }

    explicit StrongReference(const ScriptValue& script_value)
        : referenced_value_(script_value.MakeCopy()) {
      DCHECK(referenced_value_);
      referenced_value_->PreventGarbageCollection();
    }

    const T& value() const { return *(referenced_value_->GetScriptValue()); }

    // Return the referenced ScriptValue. This ScriptValue can
    // be passed back into the JavaScript bindings layer where the referenced
    // JavaScript object can be extracted from the ScriptValue.
    const ScriptValue<T>& referenced_value() const {
      return *(referenced_value_.get());
    }

    ~StrongReference() { referenced_value_->AllowGarbageCollection(); }

   private:
    scoped_ptr<ScriptValue> referenced_value_;

    DISALLOW_COPY_AND_ASSIGN(StrongReference);
  };

  // Return true iff |other| refers to the same underlying JavaScript object.
  virtual bool EqualTo(const ScriptValue& other) const = 0;

  // Returns true if this ScriptValue is referring to a NULL JavaScript object.
  bool IsNull() const { return GetScriptValue() == NULL; }

  // Creates a new ScriptValue that contains a weak reference to the same
  // underlying JavaScript object. Note that this will not prevent the object
  // from being garbage collected, one must create a Reference to do that.
  scoped_ptr<ScriptValue> MakeWeakCopy() const {
    return MakeCopy().Pass();
  }

 protected:
  virtual ~ScriptValue() {}

 private:
  // Mark/unmark this Wrappable as owning a handle to the underlying JavaScript
  // object.
  virtual void RegisterOwner(Wrappable* owner) = 0;
  virtual void DeregisterOwner(Wrappable* owner) = 0;

  // Prevent/Allow garbage collection of the underlying ScriptValue. Calls must
  // be balanced and are not idempodent. While the number of calls to |Prevent|
  // are greater than the number of calls to |Allow|, the underlying object
  // will never be garbage collected.
  virtual void PreventGarbageCollection() = 0;
  virtual void AllowGarbageCollection() = 0;

  // Return a pointer to the object that wraps the underlying JavaScript object.
  virtual const T* GetScriptValue() const = 0;

  // Make a new ScriptValue instance that holds a handle to the same underlying
  // JavaScript object. This should not be called for a ScriptValue that has a
  // NULL script object (that is, GetScriptValue() returns NULL).
  virtual scoped_ptr<ScriptValue> MakeCopy() const = 0;

  friend class scoped_ptr<ScriptValue>;
};

}  // namespace script
}  // namespace cobalt

#endif  // COBALT_SCRIPT_SCRIPT_VALUE_H_
