// Copyright Joyent, Inc. and other Node contributors.
//
// 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 "v8.h"
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>

#include "zlib.h"
#include "node.h"
#include "node_buffer.h"


namespace node {
using namespace v8;


static Persistent<String> callback_sym;
static Persistent<String> onerror_sym;

enum node_zlib_mode {
  NONE,
  DEFLATE,
  INFLATE,
  GZIP,
  GUNZIP,
  DEFLATERAW,
  INFLATERAW,
  UNZIP
};


void InitZlib(v8::Handle<v8::Object> target);


/**
 * Deflate/Inflate
 */
class ZCtx : public ObjectWrap {
 public:

  ZCtx(node_zlib_mode mode)
    : ObjectWrap()
    , init_done_(false)
    , level_(0)
    , windowBits_(0)
    , memLevel_(0)
    , strategy_(0)
    , err_(0)
    , dictionary_(NULL)
    , dictionary_len_(0)
    , flush_(0)
    , chunk_size_(0)
    , write_in_progress_(false)
    , mode_(mode)
  {
  }


  ~ZCtx() {
    Close();
  }


  void Close() {
    assert(!write_in_progress_ && "write in progress");
    assert(init_done_ && "close before init");
    assert(mode_ <= UNZIP);

    if (mode_ == DEFLATE || mode_ == GZIP || mode_ == DEFLATERAW) {
      (void)deflateEnd(&strm_);
      V8::AdjustAmountOfExternalAllocatedMemory(-kDeflateContextSize);
    } else if (mode_ == INFLATE || mode_ == GUNZIP || mode_ == INFLATERAW ||
               mode_ == UNZIP) {
      (void)inflateEnd(&strm_);
      V8::AdjustAmountOfExternalAllocatedMemory(-kInflateContextSize);
    }
    mode_ = NONE;

    if (dictionary_ != NULL) {
      delete[] dictionary_;
      dictionary_ = NULL;
    }
  }


  static Handle<Value> Close(const Arguments& args) {
    HandleScope scope;
    ZCtx *ctx = ObjectWrap::Unwrap<ZCtx>(args.This());
    ctx->Close();
    return scope.Close(Undefined());
  }


  // write(flush, in, in_off, in_len, out, out_off, out_len)
  static Handle<Value> Write(const Arguments& args) {
    HandleScope scope;
    assert(args.Length() == 7);

    ZCtx *ctx = ObjectWrap::Unwrap<ZCtx>(args.This());
    assert(ctx->init_done_ && "write before init");
    assert(ctx->mode_ != NONE && "already finalized");

    assert(!ctx->write_in_progress_ && "write already in progress");
    ctx->write_in_progress_ = true;
    ctx->Ref();

    assert(!args[0]->IsUndefined() && "must provide flush value");

    unsigned int flush = args[0]->Uint32Value();

    if (flush != Z_NO_FLUSH &&
        flush != Z_PARTIAL_FLUSH &&
        flush != Z_SYNC_FLUSH &&
        flush != Z_FULL_FLUSH &&
        flush != Z_FINISH &&
        flush != Z_BLOCK) {
      assert(0 && "Invalid flush value");
    }

    Bytef *in;
    Bytef *out;
    size_t in_off, in_len, out_off, out_len;

    if (args[1]->IsNull()) {
      // just a flush
      Bytef nada[1] = { 0 };
      in = nada;
      in_len = 0;
      in_off = 0;
    } else {
      assert(Buffer::HasInstance(args[1]));
      Local<Object> in_buf;
      in_buf = args[1]->ToObject();
      in_off = args[2]->Uint32Value();
      in_len = args[3]->Uint32Value();

      assert(in_off + in_len <= Buffer::Length(in_buf));
      in = reinterpret_cast<Bytef *>(Buffer::Data(in_buf) + in_off);
    }

    assert(Buffer::HasInstance(args[4]));
    Local<Object> out_buf = args[4]->ToObject();
    out_off = args[5]->Uint32Value();
    out_len = args[6]->Uint32Value();
    assert(out_off + out_len <= Buffer::Length(out_buf));
    out = reinterpret_cast<Bytef *>(Buffer::Data(out_buf) + out_off);

    // build up the work request
    uv_work_t* work_req = &(ctx->work_req_);

    ctx->strm_.avail_in = in_len;
    ctx->strm_.next_in = in;
    ctx->strm_.avail_out = out_len;
    ctx->strm_.next_out = out;
    ctx->flush_ = flush;

    // set this so that later on, I can easily tell how much was written.
    ctx->chunk_size_ = out_len;

    uv_queue_work(uv_default_loop(),
                  work_req,
                  ZCtx::Process,
                  ZCtx::After);

    return ctx->handle_;
  }


  // thread pool!
  // This function may be called multiple times on the uv_work pool
  // for a single write() call, until all of the input bytes have
  // been consumed.
  static void Process(uv_work_t* work_req) {
    ZCtx *ctx = container_of(work_req, ZCtx, work_req_);

    // If the avail_out is left at 0, then it means that it ran out
    // of room.  If there was avail_out left over, then it means
    // that all of the input was consumed.
    switch (ctx->mode_) {
      case DEFLATE:
      case GZIP:
      case DEFLATERAW:
        ctx->err_ = deflate(&ctx->strm_, ctx->flush_);
        break;
      case UNZIP:
      case INFLATE:
      case GUNZIP:
      case INFLATERAW:
        ctx->err_ = inflate(&ctx->strm_, ctx->flush_);

        // If data was encoded with dictionary
        if (ctx->err_ == Z_NEED_DICT && ctx->dictionary_ != NULL) {

          // Load it
          ctx->err_ = inflateSetDictionary(&ctx->strm_,
                                           ctx->dictionary_,
                                           ctx->dictionary_len_);
          if (ctx->err_ == Z_OK) {

            // And try to decode again
            ctx->err_ = inflate(&ctx->strm_, ctx->flush_);
          } else if (ctx->err_ == Z_DATA_ERROR) {

            // Both inflateSetDictionary() and inflate() return Z_DATA_ERROR.
            // Make it possible for After() to tell a bad dictionary from bad
            // input.
            ctx->err_ = Z_NEED_DICT;
          }
        }
        break;
      default:
        assert(0 && "wtf?");
    }

    // pass any errors back to the main thread to deal with.

    // now After will emit the output, and
    // either schedule another call to Process,
    // or shift the queue and call Process.
  }

  // v8 land!
  static void After(uv_work_t* work_req, int status) {
    assert(status == 0);

    HandleScope scope;
    ZCtx *ctx = container_of(work_req, ZCtx, work_req_);

    // Acceptable error states depend on the type of zlib stream.
    switch (ctx->err_) {
      case Z_OK:
      case Z_STREAM_END:
      case Z_BUF_ERROR:
        // normal statuses, not fatal
        break;
      case Z_NEED_DICT:
        if (ctx->dictionary_ == NULL) {
          ZCtx::Error(ctx, "Missing dictionary");
        } else {
          ZCtx::Error(ctx, "Bad dictionary");
        }
        return;
      default:
        // something else.
        ZCtx::Error(ctx, "Zlib error");
        return;
    }

    Local<Integer> avail_out = Integer::New(ctx->strm_.avail_out);
    Local<Integer> avail_in = Integer::New(ctx->strm_.avail_in);

    ctx->write_in_progress_ = false;

    // call the write() cb
    assert(ctx->handle_->Get(callback_sym)->IsFunction() &&
           "Invalid callback");
    Local<Value> args[2] = { avail_in, avail_out };
    MakeCallback(ctx->handle_, callback_sym, ARRAY_SIZE(args), args);

    ctx->Unref();
  }

  static void Error(ZCtx *ctx, const char *msg_) {
    const char *msg;
    if (ctx->strm_.msg != NULL) {
      msg = ctx->strm_.msg;
    } else {
      msg = msg_;
    }

    assert(ctx->handle_->Get(onerror_sym)->IsFunction() &&
           "Invalid error handler");
    HandleScope scope;
    Local<Value> args[2] = { String::New(msg),
                             Local<Value>::New(Number::New(ctx->err_)) };
    MakeCallback(ctx->handle_, onerror_sym, ARRAY_SIZE(args), args);

    // no hope of rescue.
    ctx->write_in_progress_ = false;
    ctx->Unref();
  }

  static Handle<Value> New(const Arguments& args) {
    HandleScope scope;
    if (args.Length() < 1 || !args[0]->IsInt32()) {
      return ThrowException(Exception::TypeError(String::New("Bad argument")));
    }
    node_zlib_mode mode = (node_zlib_mode) args[0]->Int32Value();

    if (mode < DEFLATE || mode > UNZIP) {
      return ThrowException(Exception::TypeError(String::New("Bad argument")));
    }

    ZCtx *ctx = new ZCtx(mode);
    ctx->Wrap(args.This());
    return args.This();
  }

  // just pull the ints out of the args and call the other Init
  static Handle<Value> Init(const Arguments& args) {
    HandleScope scope;

    assert((args.Length() == 4 || args.Length() == 5) &&
           "init(windowBits, level, memLevel, strategy, [dictionary])");

    ZCtx *ctx = ObjectWrap::Unwrap<ZCtx>(args.This());

    int windowBits = args[0]->Uint32Value();
    assert((windowBits >= 8 && windowBits <= 15) && "invalid windowBits");

    int level = args[1]->Int32Value();
    assert((level >= -1 && level <= 9) && "invalid compression level");

    int memLevel = args[2]->Uint32Value();
    assert((memLevel >= 1 && memLevel <= 9) && "invalid memlevel");

    int strategy = args[3]->Uint32Value();
    assert((strategy == Z_FILTERED ||
            strategy == Z_HUFFMAN_ONLY ||
            strategy == Z_RLE ||
            strategy == Z_FIXED ||
            strategy == Z_DEFAULT_STRATEGY) && "invalid strategy");

    char* dictionary = NULL;
    size_t dictionary_len = 0;
    if (args.Length() >= 5 && Buffer::HasInstance(args[4])) {
      Local<Object> dictionary_ = args[4]->ToObject();

      dictionary_len = Buffer::Length(dictionary_);
      dictionary = new char[dictionary_len];

      memcpy(dictionary, Buffer::Data(dictionary_), dictionary_len);
    }

    Init(ctx, level, windowBits, memLevel, strategy,
         dictionary, dictionary_len);
    SetDictionary(ctx);
    return Undefined();
  }

  static Handle<Value> Reset(const Arguments &args) {
    HandleScope scope;

    ZCtx *ctx = ObjectWrap::Unwrap<ZCtx>(args.This());

    Reset(ctx);
    SetDictionary(ctx);
    return Undefined();
  }

  static void Init(ZCtx *ctx, int level, int windowBits, int memLevel,
                   int strategy, char* dictionary, size_t dictionary_len) {
    ctx->level_ = level;
    ctx->windowBits_ = windowBits;
    ctx->memLevel_ = memLevel;
    ctx->strategy_ = strategy;

    ctx->strm_.zalloc = Z_NULL;
    ctx->strm_.zfree = Z_NULL;
    ctx->strm_.opaque = Z_NULL;

    ctx->flush_ = Z_NO_FLUSH;

    ctx->err_ = Z_OK;

    if (ctx->mode_ == GZIP || ctx->mode_ == GUNZIP) {
      ctx->windowBits_ += 16;
    }

    if (ctx->mode_ == UNZIP) {
      ctx->windowBits_ += 32;
    }

    if (ctx->mode_ == DEFLATERAW || ctx->mode_ == INFLATERAW) {
      ctx->windowBits_ *= -1;
    }

    switch (ctx->mode_) {
      case DEFLATE:
      case GZIP:
      case DEFLATERAW:
        ctx->err_ = deflateInit2(&ctx->strm_,
                                 ctx->level_,
                                 Z_DEFLATED,
                                 ctx->windowBits_,
                                 ctx->memLevel_,
                                 ctx->strategy_);
        V8::AdjustAmountOfExternalAllocatedMemory(kDeflateContextSize);
        break;
      case INFLATE:
      case GUNZIP:
      case INFLATERAW:
      case UNZIP:
        ctx->err_ = inflateInit2(&ctx->strm_, ctx->windowBits_);
        V8::AdjustAmountOfExternalAllocatedMemory(kInflateContextSize);
        break;
      default:
        assert(0 && "wtf?");
    }

    if (ctx->err_ != Z_OK) {
      ZCtx::Error(ctx, "Init error");
    }


    ctx->dictionary_ = reinterpret_cast<Bytef *>(dictionary);
    ctx->dictionary_len_ = dictionary_len;

    ctx->write_in_progress_ = false;
    ctx->init_done_ = true;
  }

  static void SetDictionary(ZCtx* ctx) {
    if (ctx->dictionary_ == NULL) return;

    ctx->err_ = Z_OK;

    switch (ctx->mode_) {
      case DEFLATE:
      case DEFLATERAW:
        ctx->err_ = deflateSetDictionary(&ctx->strm_,
                                         ctx->dictionary_,
                                         ctx->dictionary_len_);
        break;
      default:
        break;
    }

    if (ctx->err_ != Z_OK) {
      ZCtx::Error(ctx, "Failed to set dictionary");
    }
  }

  static void Reset(ZCtx* ctx) {
    ctx->err_ = Z_OK;

    switch (ctx->mode_) {
      case DEFLATE:
      case DEFLATERAW:
        ctx->err_ = deflateReset(&ctx->strm_);
        break;
      case INFLATE:
      case INFLATERAW:
        ctx->err_ = inflateReset(&ctx->strm_);
        break;
      default:
        break;
    }

    if (ctx->err_ != Z_OK) {
      ZCtx::Error(ctx, "Failed to reset stream");
    }
  }

 private:
  static const int kDeflateContextSize = 16384; // approximate
  static const int kInflateContextSize = 10240; // approximate

  bool init_done_;

  z_stream strm_;
  int level_;
  int windowBits_;
  int memLevel_;
  int strategy_;

  int err_;

  Bytef* dictionary_;
  size_t dictionary_len_;

  int flush_;

  int chunk_size_;

  bool write_in_progress_;

  uv_work_t work_req_;
  node_zlib_mode mode_;
};


void InitZlib(Handle<Object> target) {
  HandleScope scope;

  Local<FunctionTemplate> z = FunctionTemplate::New(ZCtx::New);

  z->InstanceTemplate()->SetInternalFieldCount(1);

  NODE_SET_PROTOTYPE_METHOD(z, "write", ZCtx::Write);
  NODE_SET_PROTOTYPE_METHOD(z, "init", ZCtx::Init);
  NODE_SET_PROTOTYPE_METHOD(z, "close", ZCtx::Close);
  NODE_SET_PROTOTYPE_METHOD(z, "reset", ZCtx::Reset);

  z->SetClassName(String::NewSymbol("Zlib"));
  target->Set(String::NewSymbol("Zlib"), z->GetFunction());

  callback_sym = NODE_PSYMBOL("callback");
  onerror_sym = NODE_PSYMBOL("onerror");

  // valid flush values.
  NODE_DEFINE_CONSTANT(target, Z_NO_FLUSH);
  NODE_DEFINE_CONSTANT(target, Z_PARTIAL_FLUSH);
  NODE_DEFINE_CONSTANT(target, Z_SYNC_FLUSH);
  NODE_DEFINE_CONSTANT(target, Z_FULL_FLUSH);
  NODE_DEFINE_CONSTANT(target, Z_FINISH);
  NODE_DEFINE_CONSTANT(target, Z_BLOCK);

  // return/error codes
  NODE_DEFINE_CONSTANT(target, Z_OK);
  NODE_DEFINE_CONSTANT(target, Z_STREAM_END);
  NODE_DEFINE_CONSTANT(target, Z_NEED_DICT);
  NODE_DEFINE_CONSTANT(target, Z_ERRNO);
  NODE_DEFINE_CONSTANT(target, Z_STREAM_ERROR);
  NODE_DEFINE_CONSTANT(target, Z_DATA_ERROR);
  NODE_DEFINE_CONSTANT(target, Z_MEM_ERROR);
  NODE_DEFINE_CONSTANT(target, Z_BUF_ERROR);
  NODE_DEFINE_CONSTANT(target, Z_VERSION_ERROR);

  NODE_DEFINE_CONSTANT(target, Z_NO_COMPRESSION);
  NODE_DEFINE_CONSTANT(target, Z_BEST_SPEED);
  NODE_DEFINE_CONSTANT(target, Z_BEST_COMPRESSION);
  NODE_DEFINE_CONSTANT(target, Z_DEFAULT_COMPRESSION);
  NODE_DEFINE_CONSTANT(target, Z_FILTERED);
  NODE_DEFINE_CONSTANT(target, Z_HUFFMAN_ONLY);
  NODE_DEFINE_CONSTANT(target, Z_RLE);
  NODE_DEFINE_CONSTANT(target, Z_FIXED);
  NODE_DEFINE_CONSTANT(target, Z_DEFAULT_STRATEGY);
  NODE_DEFINE_CONSTANT(target, ZLIB_VERNUM);

  NODE_DEFINE_CONSTANT(target, DEFLATE);
  NODE_DEFINE_CONSTANT(target, INFLATE);
  NODE_DEFINE_CONSTANT(target, GZIP);
  NODE_DEFINE_CONSTANT(target, GUNZIP);
  NODE_DEFINE_CONSTANT(target, DEFLATERAW);
  NODE_DEFINE_CONSTANT(target, INFLATERAW);
  NODE_DEFINE_CONSTANT(target, UNZIP);

  target->Set(String::NewSymbol("ZLIB_VERSION"), String::New(ZLIB_VERSION));
}

}  // namespace node

NODE_MODULE(node_zlib, node::InitZlib)
