/**
 * Copied from node_buffer.cc
 * see http://www.nodejs.org/
 *
 * Node's license follows:
 *
 * Copyright 2009, 2010 Ryan Lienhart Dahl. All rights reserved.
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "node_buffer.h"

#include <assert.h>
#include <stdlib.h> // malloc, free
#include <v8.h>

#include <string.h> // memcpy

#include <arpa/inet.h>  // htons, htonl

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

//#define BUFFER_DEBUG
#ifdef  BUFFER_DEBUG

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

#else

#define DBG(...)

#endif

#define MIN(a,b) ((a) < (b) ? (a) : (b))

using namespace v8;

#define SLICE_ARGS(start_arg, end_arg)                                   \
  if (!start_arg->IsInt32() || !end_arg->IsInt32()) {                    \
    return ThrowException(Exception::TypeError(                          \
          v8::String::New("Bad argument.")));                            \
  }                                                                      \
  int32_t start = start_arg->Int32Value();                               \
  int32_t end = end_arg->Int32Value();                                   \
  if (start < 0 || end < 0) {                                            \
    return ThrowException(Exception::TypeError(                          \
          v8::String::New("Bad argument.")));                            \
  }                                                                      \
  if (!(start <= end)) {                                                 \
    return ThrowException(Exception::Error(                              \
          v8::String::New("Must have start <= end")));                   \
  }                                                                      \
  if ((size_t)end > parent->length_) {                                   \
    return ThrowException(Exception::Error(                              \
          v8::String::New("end cannot be longer than parent.length")));  \
  }

static Persistent<String> length_symbol;
static Persistent<String> chars_written_sym;
static Persistent<String> write_sym;
Persistent<FunctionTemplate> Buffer::constructor_template;


// Each javascript Buffer object is backed by a Blob object.
// the Blob is just a C-level chunk of bytes.
// It has a reference count.
struct Blob_ {
  unsigned int refs;
  size_t length;
  char *data;
};
typedef struct Blob_ Blob;


static inline Blob * blob_new(size_t length) {
  DBG("blob_new E");
  Blob * blob  = (Blob*) malloc(sizeof(Blob));
  if (!blob) return NULL;

  blob->data = (char*) malloc(length);
  if (!blob->data) {
    DBG("blob_new X no memory for data");
    free(blob);
    return NULL;
  }

  V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Blob) + length);
  blob->length = length;
  blob->refs = 0;
  DBG("blob_new X");
  return blob;
}


static inline void blob_ref(Blob *blob) {
  blob->refs++;
}


static inline void blob_unref(Blob *blob) {
  assert(blob->refs > 0);
  if (--blob->refs == 0) {
    DBG("blob_unref == 0");
    //fprintf(stderr, "free %d bytes\n", blob->length);
    V8::AdjustAmountOfExternalAllocatedMemory(-(sizeof(Blob) + blob->length));
    free(blob->data);
    free(blob);
    DBG("blob_unref blob and its data freed");
  }
}

#if 0
// When someone calls buffer.asciiSlice, data is not copied. Instead V8
// references in the underlying Blob with this ExternalAsciiStringResource.
class AsciiSliceExt: public String::ExternalAsciiStringResource {
 friend class Buffer;
 public:
  AsciiSliceExt(Buffer *parent, size_t start, size_t end) {
    blob_ = parent->blob();
    blob_ref(blob_);

    assert(start <= end);
    length_ = end - start;
    assert(start + length_ <= parent->length());
    data_ = parent->data() + start;
  }


  ~AsciiSliceExt() {
    //fprintf(stderr, "free ascii slice (%d refs left)\n", blob_->refs);
    blob_unref(blob_);
  }


  const char* data() const { return data_; }
  size_t length() const { return length_; }

 private:
  const char *data_;
  size_t length_;
  Blob *blob_;
};
#endif

Buffer* Buffer::New(size_t size) {
  DBG("Buffer::New(size) E");
  HandleScope scope;

  Local<Value> arg = Integer::NewFromUnsigned(size);
  Local<Object> b = constructor_template->GetFunction()->NewInstance(1, &arg);

  DBG("Buffer::New(size) X");
  return ObjectWrap::Unwrap<Buffer>(b);
}


Handle<Value> Buffer::New(const Arguments &args) {
  DBG("Buffer::New(args) E");
  HandleScope scope;

  Buffer *buffer;
  if ((args.Length() == 0) || args[0]->IsInt32()) {
    size_t length = 0;
    if (args[0]->IsInt32()) {
      length = args[0]->Uint32Value();
    }
    buffer = new Buffer(length);
  } else if (args[0]->IsArray()) {
    Local<Array> a = Local<Array>::Cast(args[0]);
    buffer = new Buffer(a->Length());
    char *p = buffer->data();
    for (unsigned int i = 0; i < a->Length(); i++) {
      p[i] = a->Get(i)->Uint32Value();
    }
  } else if (args[0]->IsString()) {
    Local<String> s = args[0]->ToString();
    enum encoding e = ParseEncoding(args[1], UTF8);
    int length = e == UTF8 ? s->Utf8Length() : s->Length();
    buffer = new Buffer(length);
  } else if (Buffer::HasInstance(args[0]) && args.Length() > 2) {
    // var slice = new Buffer(buffer, 123, 130);
    // args: parent, start, end
    Buffer *parent = ObjectWrap::Unwrap<Buffer>(args[0]->ToObject());
    SLICE_ARGS(args[1], args[2])
    buffer = new Buffer(parent, start, end);
  } else {
    DBG("Buffer::New(args) X Bad argument");
    return ThrowException(Exception::TypeError(String::New("Bad argument")));
  }

  buffer->Wrap(args.This());
  args.This()->SetIndexedPropertiesToExternalArrayData(buffer->data(),
                                                       kExternalUnsignedByteArray,
                                                       buffer->length());
  args.This()->Set(length_symbol, Integer::New(buffer->length_));

  if (args[0]->IsString()) {
    if (write_sym.IsEmpty()) {
      write_sym = Persistent<String>::New(String::NewSymbol("write"));
    }

    Local<Value> write_v = args.This()->Get(write_sym);
    assert(write_v->IsFunction());
    Local<Function> write = Local<Function>::Cast(write_v);

    Local<Value> argv[2] = { args[0], args[1] };

    TryCatch try_catch;

    write->Call(args.This(), 2, argv);

    if (try_catch.HasCaught()) {
      ReportException(&try_catch);
    }
  }

  DBG("Buffer::New(args) X");
  return args.This();
}


Buffer::Buffer(size_t length) : ObjectWrap() {
  DBG("Buffer::Buffer(length) E");
  blob_ = blob_new(length);
  off_ = 0;
  length_ = length;

  blob_ref(blob_);

  V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer));
  DBG("Buffer::Buffer(length) X");
}


Buffer::Buffer(Buffer *parent, size_t start, size_t end) : ObjectWrap() {
  DBG("Buffer::Buffer(parent, start, end) E");
  blob_ = parent->blob_;
  assert(blob_->refs > 0);
  blob_ref(blob_);

  assert(start <= end);
  off_ = parent->off_ + start;
  length_ = end - start;
  assert(length_ <= parent->length_);

  V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer));
  DBG("Buffer::Buffer(parent, start, end) X");
}


Buffer::~Buffer() {
  DBG("Buffer::~Buffer() E");
  assert(blob_->refs > 0);
  //fprintf(stderr, "free buffer (%d refs left)\n", blob_->refs);
  blob_unref(blob_);
  V8::AdjustAmountOfExternalAllocatedMemory(-static_cast<long int>(sizeof(Buffer)));
  DBG("Buffer::~Buffer() X");
}


char* Buffer::data() {
  char *p = blob_->data + off_;
  DBG("Buffer::data() EX p=%p", p);
  return p;
}

void Buffer::NewBlob(size_t length) {
  DBG("Buffer::NewBlob(length) E");
  blob_unref(blob_);
  blob_ = blob_new(length);
  off_ = 0;
  length_ = length;

  blob_ref(blob_);

  V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer));
  DBG("Buffer::NewBlob(length) X");
}


Handle<Value> Buffer::BinarySlice(const Arguments &args) {
  DBG("Buffer::BinarySlice(args) E");
  HandleScope scope;
  Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
  SLICE_ARGS(args[0], args[1])

  const char *data = const_cast<char*>(parent->data() + start);
  //Local<String> string = String::New(data, end - start);

  Local<Value> b =  Encode(data, end - start, BINARY);

  DBG("Buffer::BinarySlice(args) X");
  return scope.Close(b);
}


Handle<Value> Buffer::AsciiSlice(const Arguments &args) {
  DBG("Buffer::AsciiSlice(args) E");
  HandleScope scope;
  Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
  SLICE_ARGS(args[0], args[1])

#if 0
  AsciiSliceExt *ext = new AsciiSliceExt(parent, start, end);
  Local<String> string = String::NewExternal(ext);
  // There should be at least two references to the blob now - the parent
  // and the slice.
  assert(parent->blob_->refs >= 2);
#endif

  const char *data = const_cast<char*>(parent->data() + start);
  Local<String> string = String::New(data, end - start);


  DBG("Buffer::AsciiSlice(args) X");
  return scope.Close(string);
}


Handle<Value> Buffer::Utf8Slice(const Arguments &args) {
  DBG("Buffer::Utf8Slice(args) E");
  HandleScope scope;
  Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
  SLICE_ARGS(args[0], args[1])
  const char *data = const_cast<char*>(parent->data() + start);
  Local<String> string = String::New(data, end - start);
  DBG("Buffer::Utf8Slice(args) X");
  return scope.Close(string);
}


Handle<Value> Buffer::Slice(const Arguments &args) {
  DBG("Buffer::Slice(args) E");
  HandleScope scope;
  Local<Value> argv[3] = { args.This(), args[0], args[1] };
  Local<Object> slice =
    constructor_template->GetFunction()->NewInstance(3, argv);
  DBG("Buffer::Slice(args) X");
  return scope.Close(slice);
}


// var bytesCopied = buffer.copy(target, targetStart, sourceStart, sourceEnd);
Handle<Value> Buffer::Copy(const Arguments &args) {
  DBG("Buffer::Copy(args) E");
  HandleScope scope;

  Buffer *source = ObjectWrap::Unwrap<Buffer>(args.This());

  if (!Buffer::HasInstance(args[0])) {
    DBG("Buffer::Copy(args) X arg[0] not buffer");
    return ThrowException(Exception::TypeError(String::New(
            "First arg should be a Buffer")));
  }

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

  ssize_t target_start = args[1]->Int32Value();
  ssize_t source_start = args[2]->Int32Value();
  ssize_t source_end = args[3]->IsInt32() ? args[3]->Int32Value()
                                          : source->length();

  if (source_end < source_start) {
    DBG("Buffer::Copy(args) X end < start");
    return ThrowException(Exception::Error(String::New(
            "sourceEnd < sourceStart")));
  }

  if (target_start < 0 || ((size_t)target_start) > target->length()) {
    DBG("Buffer::Copy(args) X targetStart bad");
    return ThrowException(Exception::Error(String::New(
            "targetStart out of bounds")));
  }

  if (source_start < 0 || ((size_t)source_start) > source->length()) {
    DBG("Buffer::Copy(args) X base source start");
    return ThrowException(Exception::Error(String::New(
            "sourceStart out of bounds")));
  }

  if (source_end < 0 || ((size_t)source_end) > source->length()) {
    DBG("Buffer::Copy(args) X bad source");
    return ThrowException(Exception::Error(String::New(
            "sourceEnd out of bounds")));
  }

  ssize_t to_copy = MIN(source_end - source_start,
                        target->length() - target_start);

  memcpy((void*)(target->data() + target_start),
         (const void*)(source->data() + source_start),
         to_copy);

  DBG("Buffer::Copy(args) X");
  return scope.Close(Integer::New(to_copy));
}


// var charsWritten = buffer.utf8Write(string, offset);
Handle<Value> Buffer::Utf8Write(const Arguments &args) {
  DBG("Buffer::Utf8Write(args) X");
  HandleScope scope;
  Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());

  if (!args[0]->IsString()) {
  DBG("Buffer::Utf8Write(args) X arg[0] not string");
    return ThrowException(Exception::TypeError(String::New(
            "Argument must be a string")));
  }

  Local<String> s = args[0]->ToString();

  size_t offset = args[1]->Int32Value();

  if (offset >= buffer->length_) {
    DBG("Buffer::Utf8Write(args) X offset bad");
    return ThrowException(Exception::TypeError(String::New(
            "Offset is out of bounds")));
  }

  const char *p = buffer->data() + offset;

  int char_written;

  int written = s->WriteUtf8((char*)p,
                             buffer->length_ - offset,
                             &char_written,
                             String::HINT_MANY_WRITES_EXPECTED);

  constructor_template->GetFunction()->Set(chars_written_sym,
                                           Integer::New(char_written));

  if (written > 0 && p[written-1] == '\0') written--;

  DBG("Buffer::Utf8Write(args) X");
  return scope.Close(Integer::New(written));
}


// var charsWritten = buffer.asciiWrite(string, offset);
Handle<Value> Buffer::AsciiWrite(const Arguments &args) {
  DBG("Buffer::AsciiWrite(args) E");
  HandleScope scope;

  Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());

  if (!args[0]->IsString()) {
    DBG("Buffer::AsciiWrite(args) X arg[0] not string");
    return ThrowException(Exception::TypeError(String::New(
            "Argument must be a string")));
  }

  Local<String> s = args[0]->ToString();

  size_t offset = args[1]->Int32Value();

  if (offset >= buffer->length_) {
    DBG("Buffer::AsciiWrite(args) X bad offset");
    return ThrowException(Exception::TypeError(String::New(
            "Offset is out of bounds")));
  }

  const char *p = buffer->data() + offset;

  size_t towrite = MIN((unsigned long) s->Length(), buffer->length_ - offset);

  int written = s->WriteAscii((char*)p, 0, towrite, String::HINT_MANY_WRITES_EXPECTED);
  DBG("Buffer::AsciiWrite(args) X");
  return scope.Close(Integer::New(written));
}


Handle<Value> Buffer::BinaryWrite(const Arguments &args) {
  DBG("Buffer::BinaryWrite(args) E");
  HandleScope scope;

  Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());

  if (!args[0]->IsString()) {
    DBG("Buffer::BinaryWrite(args) X arg[0] not string");
    return ThrowException(Exception::TypeError(String::New(
            "Argument must be a string")));
  }

  Local<String> s = args[0]->ToString();

  size_t offset = args[1]->Int32Value();

  if (offset >= buffer->length_) {
    DBG("Buffer::BinaryWrite(args) X offset bad");
    return ThrowException(Exception::TypeError(String::New(
            "Offset is out of bounds")));
  }

  char *p = (char*)buffer->data() + offset;

  size_t towrite = MIN((unsigned long) s->Length(), buffer->length_ - offset);

  int written = DecodeWrite(p, towrite, s, BINARY);
  DBG("Buffer::BinaryWrite(args) X");
  return scope.Close(Integer::New(written));
}


// buffer.unpack(format, index);
// Starting at 'index', unpacks binary from the buffer into an array.
// 'format' is a string
//
//  FORMAT  RETURNS
//    N     uint32_t   a 32bit unsigned integer in network byte order
//    n     uint16_t   a 16bit unsigned integer in network byte order
//    o     uint8_t    a 8bit unsigned integer
Handle<Value> Buffer::Unpack(const Arguments &args) {
  DBG("Buffer::Unpack(args) E");
  HandleScope scope;
  Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());

  if (!args[0]->IsString()) {
    DBG("Buffer::Unpack(args) X arg[0] not string");
    return ThrowException(Exception::TypeError(String::New(
            "Argument must be a string")));
  }

  String::AsciiValue format(args[0]->ToString());
  uint32_t index = args[1]->Uint32Value();

#define OUT_OF_BOUNDS ThrowException(Exception::Error(String::New("Out of bounds")))

  Local<Array> array = Array::New(format.length());

  uint8_t  uint8;
  uint16_t uint16;
  uint32_t uint32;

  for (int i = 0; i < format.length(); i++) {
    switch ((*format)[i]) {
      // 32bit unsigned integer in network byte order
      case 'N':
        if (index + 3 >= buffer->length_) return OUT_OF_BOUNDS;
        uint32 = htonl(*(uint32_t*)(buffer->data() + index));
        array->Set(Integer::New(i), Integer::NewFromUnsigned(uint32));
        index += 4;
        break;

      // 16bit unsigned integer in network byte order
      case 'n':
        if (index + 1 >= buffer->length_) return OUT_OF_BOUNDS;
        uint16 = htons(*(uint16_t*)(buffer->data() + index));
        array->Set(Integer::New(i), Integer::NewFromUnsigned(uint16));
        index += 2;
        break;

      // a single octet, unsigned.
      case 'o':
        if (index >= buffer->length_) return OUT_OF_BOUNDS;
        uint8 = (uint8_t)buffer->data()[index];
        array->Set(Integer::New(i), Integer::NewFromUnsigned(uint8));
        index += 1;
        break;

      default:
        DBG("Buffer::Unpack(args) X unknown format character");
        return ThrowException(Exception::Error(
              String::New("Unknown format character")));
    }
  }

  DBG("Buffer::Unpack(args) X");
  return scope.Close(array);
}


// var nbytes = Buffer.byteLength("string", "utf8")
Handle<Value> Buffer::ByteLength(const Arguments &args) {
  DBG("Buffer::ByteLength(args) E");
  HandleScope scope;

  if (!args[0]->IsString()) {
    DBG("Buffer::ByteLength(args) X arg[0] not a string");
    return ThrowException(Exception::TypeError(String::New(
            "Argument must be a string")));
  }

  Local<String> s = args[0]->ToString();
  enum encoding e = ParseEncoding(args[1], UTF8);

  Local<Integer> length =
    Integer::New(e == UTF8 ? s->Utf8Length() : s->Length());

  DBG("Buffer::ByteLength(args) X");
  return scope.Close(length);
}

void Buffer::InitializeObjectTemplate(Handle<ObjectTemplate> target) {
  DBG("InitializeObjectTemplate(target) E:");
  HandleScope scope;

  length_symbol = Persistent<String>::New(String::NewSymbol("length"));
  chars_written_sym = Persistent<String>::New(String::NewSymbol("_charsWritten"));

  Local<FunctionTemplate> t = FunctionTemplate::New(Buffer::New);
  constructor_template = Persistent<FunctionTemplate>::New(t);
  constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
  constructor_template->SetClassName(String::NewSymbol("Buffer"));

  // copy free
  SET_PROTOTYPE_METHOD(constructor_template, "binarySlice", Buffer::BinarySlice);
  SET_PROTOTYPE_METHOD(constructor_template, "asciiSlice", Buffer::AsciiSlice);
  SET_PROTOTYPE_METHOD(constructor_template, "slice", Buffer::Slice);
  // TODO SET_PROTOTYPE_METHOD(t, "utf16Slice", Utf16Slice);
  // copy
  SET_PROTOTYPE_METHOD(constructor_template, "utf8Slice", Buffer::Utf8Slice);

  SET_PROTOTYPE_METHOD(constructor_template, "utf8Write", Buffer::Utf8Write);
  SET_PROTOTYPE_METHOD(constructor_template, "asciiWrite", Buffer::AsciiWrite);
  SET_PROTOTYPE_METHOD(constructor_template, "binaryWrite", Buffer::BinaryWrite);
  SET_PROTOTYPE_METHOD(constructor_template, "unpack", Buffer::Unpack);
  SET_PROTOTYPE_METHOD(constructor_template, "copy", Buffer::Copy);

  SET_PROTOTYPE_METHOD(constructor_template, "byteLength", Buffer::ByteLength);

  target->Set(String::NewSymbol("Buffer"), constructor_template);
  DBG("InitializeObjectTemplate(target) X:");
}
