/**
 * File:   session.cpp
 * Author: Alexander Ksenofontov <aksenofo@yahoo.ru>
 *
 * Created on August 14, 2016, 14:13 PM
 */


#include "session.h"
#include "synchronize_worker.h"
#include "environment.h"

using namespace Nan;
using namespace v8;

Nan::Persistent<v8::Function> Session::constructor;

NAN_MODULE_INIT(Session::Init) {
    Nan::HandleScope scope;
    auto cname = Nan::New("Session").ToLocalChecked();
    auto ctor = Nan::New<v8::FunctionTemplate>(New);
    auto ctorInst = ctor->InstanceTemplate(); // target for member functions
    ctor->SetClassName(cname); // as `ctor.name` in JS
    ctorInst->SetInternalFieldCount(1); // for ObjectWrap, it should set 1

    Nan::SetPrototypeMethod(ctor, "synchronize", Synchronize);

    Nan::Set(target, cname, Nan::GetFunction(ctor).ToLocalChecked());

    REG_READONLY(ctorInst, HttpUrl)
    REG_READONLY(ctorInst, TorrentUrl)
    REG_READONLY(ctorInst, LocalRoot)

    constructor.Reset(ctor->GetFunction());
}

NAN_METHOD(Session::New) {
    Nan::HandleScope scope;

    if (!info.IsConstructCall()) {
	std::vector<v8::Local<v8::Value>> args(info.Length());
	for (std::size_t i = 0; i < args.size(); ++i) args[i] = info[i];
	auto inst = Nan::NewInstance(info.Callee(), args.size(), args.data());
	if (!inst.IsEmpty()) info.GetReturnValue().Set(inst.ToLocalChecked());
	    return;
    }

    if(info.Length() < 3 )
		Nan::ThrowError("Not enough parameters");
  
    remote_info ri = {
		*Nan::Utf8String(info[0]),
		*Nan::Utf8String(info[1]),
		get_full_path_name(*Nan::Utf8String(info[2]))
    };

    auto object(new Session(ri));
    object->Wrap(info.This());
}

NAN_METHOD(Session::Synchronize) {
    Nan::HandleScope scope;
    if(info.Length() < 2 )
		Nan::ThrowError("Not enough parameters");
    Callback *periodical(new Callback(info[0].As<v8::Function>()));
    Callback *finished(new Callback(info[1].As<v8::Function>()));

    auto This(Nan::ObjectWrap::Unwrap<Session>(info.Holder()));
    v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object>> owner(info.GetIsolate(), info.Holder());
    auto worker(new SynchronizeWorker(owner, periodical, finished, This->ri_));
    AsyncQueueWorker(worker);
}
