// Copyright 2010 Google Inc.
//
// 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.

#include "protobuf_v8.h"

#include <map>
#include <string>
#include <iostream>
#include <sstream>

#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>

#include "logging.h"
#include "util.h"

#include "node_buffer.h"
#include "node_object_wrap.h"

#include "node_util.h"

//#define PROTOBUF_V8_DEBUG
#ifdef  PROTOBUF_V8_DEBUG

#define DBG(...) ALOGD(__VA_ARGS__)

#else

#define DBG(...)

#endif

using google::protobuf::Descriptor;
using google::protobuf::DescriptorPool;
using google::protobuf::DynamicMessageFactory;
using google::protobuf::FieldDescriptor;
using google::protobuf::FileDescriptorSet;
using google::protobuf::Message;
using google::protobuf::Reflection;

//using ObjectWrap;
//using Buffer;

using std::map;
using std::string;

using v8::Array;
using v8::AccessorInfo;
using v8::Arguments;
using v8::Boolean;
using v8::Context;
using v8::External;
using v8::Function;
using v8::FunctionTemplate;
using v8::Integer;
using v8::Handle;
using v8::HandleScope;
using v8::InvocationCallback;
using v8::Local;
using v8::NamedPropertyGetter;
using v8::Number;
using v8::Object;
using v8::ObjectTemplate;
using v8::Persistent;
using v8::Script;
using v8::String;
using v8::Value;
using v8::V8;

namespace protobuf_v8 {

  template <typename T>
  static T* UnwrapThis(const Arguments& args) {
    return ObjectWrap::Unwrap<T>(args.This());
  }

  template <typename T>
  static T* UnwrapThis(const AccessorInfo& args) {
    return ObjectWrap::Unwrap<T>(args.This());
  }

  Persistent<FunctionTemplate> SchemaTemplate;
  Persistent<FunctionTemplate> TypeTemplate;
  Persistent<FunctionTemplate> ParseTemplate;
  Persistent<FunctionTemplate> SerializeTemplate;

  class Schema : public ObjectWrap {
  public:
    Schema(Handle<Object> self, const DescriptorPool* pool)
        : pool_(pool) {
      DBG("Schema::Schema E:");
      factory_.SetDelegateToGeneratedFactory(true);
      self->SetInternalField(1, Array::New());
      Wrap(self);
      DBG("Schema::Schema X:");
    }

    virtual ~Schema() {
      DBG("~Schema::Schema E:");
      if (pool_ != DescriptorPool::generated_pool())
        delete pool_;
      DBG("~Schema::Schema X:");
    }

    class Type : public ObjectWrap {
    public:
      Schema* schema_;
      const Descriptor* descriptor_;

      Message* NewMessage() const {
        DBG("Type::NewMessage() EX:");
        return schema_->NewMessage(descriptor_);
      }

      Handle<Function> Constructor() const {
        DBG("Type::Constrocutor() EX:");
        return handle_->GetInternalField(2).As<Function>();
      }

      Local<Object> NewObject(Handle<Value> properties) const {
        DBG("Type::NewObjext(properties) EX:");
        return Constructor()->NewInstance(1, &properties);
      }

      Type(Schema* schema, const Descriptor* descriptor, Handle<Object> self)
        : schema_(schema), descriptor_(descriptor) {
        DBG("Type::Type(schema, descriptor, self) E:");
        // Generate functions for bulk conversion between a JS object
        // and an array in descriptor order:
        //   from = function(arr) { this.f0 = arr[0]; this.f1 = arr[1]; ... }
        //   to   = function()    { return [ this.f0, this.f1, ... ] }
        // This is faster than repeatedly calling Get/Set on a v8::Object.
        std::ostringstream from, to;
        from << "(function(arr) { if(arr) {";
        to << "(function() { return [ ";

        for (int i = 0; i < descriptor->field_count(); i++) {
          from <<
            "var x = arr[" << i << "]; "
            "if(x !== undefined) this['" <<
            descriptor->field(i)->camelcase_name() <<
            "'] = x; ";

          if (i > 0) to << ", ";
          to << "this['" << descriptor->field(i)->camelcase_name() << "']";
          DBG("field name=%s", descriptor->field(i)->name().c_str());
        }

        from << " }})";
        to << " ]; })";

        // managed type->schema link
        self->SetInternalField(1, schema_->handle_);

        Handle<Function> constructor =
          Script::Compile(String::New(from.str().c_str()))->Run().As<Function>();
        constructor->SetHiddenValue(String::New("type"), self);

        Handle<Function> bind =
          Script::Compile(String::New(
              "(function(self) {"
              "  var f = this;"
              "  return function(arg) {"
              "    return f.call(self, arg);"
              "  };"
              "})"))->Run().As<Function>();
        Handle<Value> arg = self;
        constructor->Set(String::New("parse"), bind->Call(ParseTemplate->GetFunction(), 1, &arg));
        constructor->Set(String::New("serialize"), bind->Call(SerializeTemplate->GetFunction(), 1, &arg));
        self->SetInternalField(2, constructor);
        self->SetInternalField(3, Script::Compile(String::New(to.str().c_str()))->Run());

        Wrap(self);
        DBG("Type::Type(schema, descriptor, self) X:");
      }

#define GET(TYPE)                                                        \
      (index >= 0 ?                                                      \
       reflection->GetRepeated##TYPE(instance, field, index) :           \
       reflection->Get##TYPE(instance, field))

      static Handle<Value> ToJs(const Message& instance,
                                const Reflection* reflection,
                                const FieldDescriptor* field,
                                const Type* message_type,
                                int index) {
        DBG("Type::ToJs(instance, refelction, field, message_type) E:");
        switch (field->cpp_type()) {
        case FieldDescriptor::CPPTYPE_MESSAGE:
          DBG("Type::ToJs CPPTYPE_MESSAGE");
          return message_type->ToJs(GET(Message));
        case FieldDescriptor::CPPTYPE_STRING: {
          DBG("Type::ToJs CPPTYPE_STRING");
          const string& value = GET(String);
          return String::New(value.data(), value.length());
        }
        case FieldDescriptor::CPPTYPE_INT32:
          DBG("Type::ToJs CPPTYPE_INT32");
          return Integer::New(GET(Int32));
        case FieldDescriptor::CPPTYPE_UINT32:
          DBG("Type::ToJs CPPTYPE_UINT32");
          return Integer::NewFromUnsigned(GET(UInt32));
        case FieldDescriptor::CPPTYPE_INT64:
          DBG("Type::ToJs CPPTYPE_INT64");
          return Number::New(GET(Int64));
        case FieldDescriptor::CPPTYPE_UINT64:
          DBG("Type::ToJs CPPTYPE_UINT64");
          return Number::New(GET(UInt64));
        case FieldDescriptor::CPPTYPE_FLOAT:
          DBG("Type::ToJs CPPTYPE_FLOAT");
          return Number::New(GET(Float));
        case FieldDescriptor::CPPTYPE_DOUBLE:
          DBG("Type::ToJs CPPTYPE_DOUBLE");
          return Number::New(GET(Double));
        case FieldDescriptor::CPPTYPE_BOOL:
          DBG("Type::ToJs CPPTYPE_BOOL");
          return Boolean::New(GET(Bool));
        case FieldDescriptor::CPPTYPE_ENUM:
          DBG("Type::ToJs CPPTYPE_ENUM");
          return String::New(GET(Enum)->name().c_str());
        }

        return Handle<Value>();  // NOTREACHED
      }
#undef GET

      Handle<Object> ToJs(const Message& instance) const {
        DBG("Type::ToJs(Message) E:");
        const Reflection* reflection = instance.GetReflection();
        const Descriptor* descriptor = instance.GetDescriptor();

        Handle<Array> properties = Array::New(descriptor->field_count());
        for (int i = 0; i < descriptor->field_count(); i++) {
          HandleScope scope;

          const FieldDescriptor* field = descriptor->field(i);
          bool repeated = field->is_repeated();
          if (repeated && !reflection->FieldSize(instance, field)) {
            DBG("Ignore repeated field with no size in reflection data");
            continue;
          }
          if (!repeated && !reflection->HasField(instance, field)) {
            DBG("Ignore field with no field in relfection data");
            continue;
          }

          const Type* child_type =
            (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
            schema_->GetType(field->message_type()) : NULL;

          Handle<Value> value;
          if (field->is_repeated()) {
            int size = reflection->FieldSize(instance, field);
            Handle<Array> array = Array::New(size);
            for (int j = 0; j < size; j++) {
              array->Set(j, ToJs(instance, reflection, field, child_type, j));
            }
            value = array;
          } else {
            value = ToJs(instance, reflection, field, child_type, -1);
          }

          DBG("Type::ToJs: set property[%d]=%s", i, ToCString(value));
          properties->Set(i, value);
        }

        DBG("Type::ToJs(Message) X:");
        return NewObject(properties);
      }

      static Handle<Value> Parse(const Arguments& args) {
        DBG("Type::Parse(args) E:");
        Type* type = UnwrapThis<Type>(args);
        Buffer* buf = ObjectWrap::Unwrap<Buffer>(args[0]->ToObject());

        Message* message = type->NewMessage();
        message->ParseFromArray(buf->data(), buf->length());
        Handle<Object> result = type->ToJs(*message);
        delete message;

        DBG("Type::Parse(args) X:");
        return result;
      }

#define SET(TYPE, EXPR)                                                 \
      if (repeated) reflection->Add##TYPE(instance, field, EXPR);       \
      else reflection->Set##TYPE(instance, field, EXPR)

      static bool ToProto(Message* instance,
                          const FieldDescriptor* field,
                          Handle<Value> value,
                          const Type* type,
                          bool repeated) {
        DBG("Type::ToProto(instance, field, value, type, repeated) E:");
        bool ok = true;
        HandleScope scope;

        DBG("Type::ToProto field->name()=%s", field->name().c_str());
        const Reflection* reflection = instance->GetReflection();
        switch (field->cpp_type()) {
        case FieldDescriptor::CPPTYPE_MESSAGE:
          DBG("Type::ToProto CPPTYPE_MESSAGE");
          ok = type->ToProto(repeated ?
                                reflection->AddMessage(instance, field) :
                                reflection->MutableMessage(instance, field),
                                    value.As<Object>());
          break;
        case FieldDescriptor::CPPTYPE_STRING: {
          DBG("Type::ToProto CPPTYPE_STRING");
          String::AsciiValue ascii(value);
          SET(String, string(*ascii, ascii.length()));
          break;
        }
        case FieldDescriptor::CPPTYPE_INT32:
          DBG("Type::ToProto CPPTYPE_INT32");
          SET(Int32, value->NumberValue());
          break;
        case FieldDescriptor::CPPTYPE_UINT32:
          DBG("Type::ToProto CPPTYPE_UINT32");
          SET(UInt32, value->NumberValue());
          break;
        case FieldDescriptor::CPPTYPE_INT64:
          DBG("Type::ToProto CPPTYPE_INT64");
          SET(Int64, value->NumberValue());
          break;
        case FieldDescriptor::CPPTYPE_UINT64:
          DBG("Type::ToProto CPPTYPE_UINT64");
          SET(UInt64, value->NumberValue());
          break;
        case FieldDescriptor::CPPTYPE_FLOAT:
          DBG("Type::ToProto CPPTYPE_FLOAT");
          SET(Float, value->NumberValue());
          break;
        case FieldDescriptor::CPPTYPE_DOUBLE:
          DBG("Type::ToProto CPPTYPE_DOUBLE");
          SET(Double, value->NumberValue());
          break;
        case FieldDescriptor::CPPTYPE_BOOL:
          DBG("Type::ToProto CPPTYPE_BOOL");
          SET(Bool, value->BooleanValue());
          break;
        case FieldDescriptor::CPPTYPE_ENUM:
          DBG("Type::ToProto CPPTYPE_ENUM");

          // Don't use SET as vd can be NULL
          char error_buff[256];
          const google::protobuf::EnumValueDescriptor* vd;
          int i32_value = 0;
          const char *str_value = NULL;
          const google::protobuf::EnumDescriptor* ed = field->enum_type();

          if (value->IsNumber()) {
            i32_value = value->Int32Value();
            vd = ed->FindValueByNumber(i32_value);
            if (vd == NULL) {
              snprintf(error_buff, sizeof(error_buff),
                  "Type::ToProto Bad enum value, %d is not a member of enum %s",
                      i32_value, ed->full_name().c_str());
            }
          } else {
            str_value = ToCString(value);
            // TODO: Why can str_value be corrupted sometimes?
            ALOGD("str_value=%s", str_value);
            vd = ed->FindValueByName(str_value);
            if (vd == NULL) {
              snprintf(error_buff, sizeof(error_buff),
                  "Type::ToProto Bad enum value, %s is not a member of enum %s",
                      str_value, ed->full_name().c_str());
            }
          }
          if (vd != NULL) {
            if (repeated) {
               reflection->AddEnum(instance, field, vd);
            } else {
               reflection->SetEnum(instance, field, vd);
            }
          } else {
            v8::ThrowException(String::New(error_buff));
            ok = false;
          }
          break;
        }
        DBG("Type::ToProto(instance, field, value, type, repeated) X: ok=%d", ok);
        return ok;
      }
#undef SET

      bool ToProto(Message* instance, Handle<Object> src) const {
        DBG("ToProto(Message *, Handle<Object>) E:");

        Handle<Function> to_array = handle_->GetInternalField(3).As<Function>();
        Handle<Array> properties = to_array->Call(src, 0, NULL).As<Array>();
        bool ok = true;
        for (int i = 0; ok && (i < descriptor_->field_count()); i++) {
          Handle<Value> value = properties->Get(i);
          if (value->IsUndefined()) continue;

          const FieldDescriptor* field = descriptor_->field(i);
          const Type* child_type =
            (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
            schema_->GetType(field->message_type()) : NULL;
          if (field->is_repeated()) {
            if(!value->IsArray()) {
              ok = ToProto(instance, field, value, child_type, true);
            } else {
              Handle<Array> array = value.As<Array>();
              int length = array->Length();
              for (int j = 0; ok && (j < length); j++) {
                ok = ToProto(instance, field, array->Get(j), child_type, true);
              }
            }
          } else {
            ok = ToProto(instance, field, value, child_type, false);
          }
        }
        DBG("ToProto(Message *, Handle<Object>) X: ok=%d", ok);
        return ok;
      }

      static Handle<Value> Serialize(const Arguments& args) {
        Handle<Value> result;
        DBG("Serialize(Arguments&) E:");
        if (!args[0]->IsObject()) {
          DBG("Serialize(Arguments&) X: not an object");
          return v8::ThrowException(args[0]);
        }

        Type* type = UnwrapThis<Type>(args);
        Message* message = type->NewMessage();
        if (type->ToProto(message, args[0].As<Object>())) {
          int length = message->ByteSize();
          Buffer* buffer = Buffer::New(length);
          message->SerializeWithCachedSizesToArray((google::protobuf::uint8*)buffer->data());
          delete message;

          result = buffer->handle_;
        } else {
          result = v8::Undefined();
        }
        DBG("Serialize(Arguments&) X");
        return result;
      }

      static Handle<Value> ToString(const Arguments& args) {
        return String::New(UnwrapThis<Type>(args)->descriptor_->full_name().c_str());
      }
    };

    Message* NewMessage(const Descriptor* descriptor) {
      DBG("Schema::NewMessage(descriptor) EX:");
      return factory_.GetPrototype(descriptor)->New();
    }

    Type* GetType(const Descriptor* descriptor) {
      DBG("Schema::GetType(descriptor) E:");
      Type* result = types_[descriptor];
      if (result) return result;

      result = types_[descriptor] =
        new Type(this, descriptor, TypeTemplate->GetFunction()->NewInstance());

      // managed schema->[type] link
      Handle<Array> types = handle_->GetInternalField(1).As<Array>();
      types->Set(types->Length(), result->handle_);
      DBG("Schema::GetType(descriptor) X:");
      return result;
    }

    const DescriptorPool* pool_;
    map<const Descriptor*, Type*> types_;
    DynamicMessageFactory factory_;

    static Handle<Value> GetType(const Local<String> name,
                                 const AccessorInfo& args) {
      DBG("Schema::GetType(name, args) E:");
      Schema* schema = UnwrapThis<Schema>(args);
      const Descriptor* descriptor =
        schema->pool_->FindMessageTypeByName(*String::AsciiValue(name));

      DBG("Schema::GetType(name, args) X:");
      return descriptor ?
        schema->GetType(descriptor)->Constructor() :
        Handle<Function>();
    }

    static Handle<Value> NewSchema(const Arguments& args) {
      DBG("Schema::NewSchema E: args.Length()=%d", args.Length());
      if (!args.Length()) {
        return (new Schema(args.This(),
                           DescriptorPool::generated_pool()))->handle_;
      }

      Buffer* buf = ObjectWrap::Unwrap<Buffer>(args[0]->ToObject());

      FileDescriptorSet descriptors;
      if (!descriptors.ParseFromArray(buf->data(), buf->length())) {
        DBG("Schema::NewSchema X: bad descriptor");
        return v8::ThrowException(String::New("Malformed descriptor"));
      }

      DescriptorPool* pool = new DescriptorPool;
      for (int i = 0; i < descriptors.file_size(); i++) {
        pool->BuildFile(descriptors.file(i));
      }

      DBG("Schema::NewSchema X");
      return (new Schema(args.This(), pool))->handle_;
    }
  };

  void Init() {
    DBG("Init E:");
    HandleScope handle_scope;

    TypeTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New());
    TypeTemplate->SetClassName(String::New("Type"));
    // native self
    // owning schema (so GC can manage our lifecyle)
    // constructor
    // toArray
    TypeTemplate->InstanceTemplate()->SetInternalFieldCount(4);

    SchemaTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Schema::NewSchema));
    SchemaTemplate->SetClassName(String::New("Schema"));
    // native self
    // array of types (so GC can manage our lifecyle)
    SchemaTemplate->InstanceTemplate()->SetInternalFieldCount(2);
    SchemaTemplate->InstanceTemplate()->SetNamedPropertyHandler(Schema::GetType);

    ParseTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Schema::Type::Parse));
    SerializeTemplate = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Schema::Type::Serialize));

    DBG("Init X:");
  }

}  // namespace protobuf_v8

extern "C" void SchemaObjectTemplateInit(Handle<ObjectTemplate> target) {
  DBG("SchemaObjectTemplateInit(target) EX:");
  target->Set(String::New("Schema"), protobuf_v8::SchemaTemplate);
}
