/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
 * Copyright 2008-2013 Pelican Mapping
 * http://osgearth.org
 *
 * osgEarth is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#ifndef OSGEARTH_DRIVER_V8_UTIL_H
#define OSGEARTH_DRIVER_V8_UTIL_H 1

#include <v8.h>
#include <iostream>

#define V8_OBJECT_TYPE_PROPERTY "__object_type"

class V8Util
{
public:
  typedef std::map< std::string, v8::Handle<v8::Value> > V8PropertyMap;

  template<typename T>
  static v8::Handle<v8::Object> WrapObject(v8::Isolate* isolate, T* obj,  v8::Handle<v8::ObjectTemplate> templ)
  {
    return WrapObject(isolate, obj, templ, V8PropertyMap());
  }

  template<typename T>
  static v8::Handle<v8::Object> WrapObject(v8::Isolate* isolate, T* obj,  v8::Handle<v8::ObjectTemplate> templ, const V8PropertyMap& props)
  {
    v8::HandleScope handle_scope(isolate);

    v8::Handle<v8::Object> result = templ->NewInstance();

    v8::Handle<v8::External> obj_ptr = v8::External::New(obj);
    result->SetInternalField(0, obj_ptr);

    for (V8PropertyMap::const_iterator it = props.begin(); it != props.end(); ++it)
      result->Set(v8::String::New(it->first.c_str(), it->first.length()), it->second);

    return handle_scope.Close(result);
  }

  template<typename T>
  static T* UnwrapObject(v8::Handle<v8::Object> obj)
  {
    v8::Handle<v8::External> field = v8::Handle<v8::External>::Cast(obj->GetInternalField(0));
    void* ptr = field->Value();
    return static_cast<T*>(ptr);
  }

  static bool CheckObjectType(v8::Handle<v8::Object> obj, const std::string& objType)
  {
    v8::Local<v8::Value> typeVal = obj->Get(v8::String::New(V8_OBJECT_TYPE_PROPERTY));
    if (!typeVal.IsEmpty())
    {
      v8::String::Utf8Value utf8_value(typeVal);
      std::string typeStr(*utf8_value);

      if (typeStr == objType)
        return true;
    }

    return false;
  }
};

#endif // OSGEARTH_DRIVER_V8_UTIL_H
