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


#include <stddef.h>
#include <sys/types.h>
#include <iostream>
#include <nan.h>
#include "declarations.h"
#include "session.h"
#include "environment.h"
#include <libtorrent/session.hpp>

using namespace Nan;
using namespace v8;

using namespace libtorrent;
namespace lt = libtorrent;

#define DEFAUTL_TORRENT_PORT 6881
std::atomic<uint32_t> torrent_to_http_switch_timeout_milisec(20000);

#define VALIDATE_TOR_LOADED()\
    if (!torrent_session) {\
        return Nan::ThrowError("Torrent is not active. Start torrent first.");\
    }

std::shared_ptr<Environment> torrent_session(nullptr);

int listen_port(DEFAUTL_TORRENT_PORT);

NAN_METHOD(version) {
    info.GetReturnValue().Set(Nan::New<String>("0.0.1.1").ToLocalChecked());
}

NAN_METHOD(start) {
    Nan::HandleScope scope;
    if (torrent_session) {
		return Nan::ThrowError("Torrent is already started");
    }

	if(info.Length() >= 1)
		listen_port = info[0]->Uint32Value();
	if (info.Length() >= 2)
		torrent_to_http_switch_timeout_milisec.exchange((uint32_t)(info[1]->NumberValue() * 1000.0));
	torrent_session.reset(new Environment(listen_port));
}

NAN_METHOD(stop) {
	Nan::HandleScope scope;
	VALIDATE_TOR_LOADED();
	torrent_session.reset();
}

NAN_METHOD(set_timeout) {
	Nan::HandleScope scope;
	if (info.Length() < 1) {
		return Nan::ThrowError("Torrent is already started");
	}
	torrent_to_http_switch_timeout_milisec.exchange((uint32_t)(info[0]->NumberValue() * 1000.0));
}

NAN_METHOD(create_session) {
    VALIDATE_TOR_LOADED();
	std::unique_ptr<Local<Value>[]> argv(new Local<Value>[info.Length()]);
	for (auto i(0); i < info.Length(); i++) {
		argv.get()[i] = info[i];
	}
	info.GetReturnValue().Set(Nan::New<v8::Function>(Session::constructor)
		->NewInstance(info.Length(), argv.get()));
}

NAN_MODULE_INIT(Init) {
    Nan::Set(target, New<String>("version").ToLocalChecked(), GetFunction(New<FunctionTemplate>(version)).ToLocalChecked());
    Nan::Set(target, New<String>("start").ToLocalChecked(), GetFunction(New<FunctionTemplate>(start)).ToLocalChecked());
	Nan::Set(target, New<String>("stop").ToLocalChecked(), GetFunction(New<FunctionTemplate>(stop)).ToLocalChecked());
	Nan::Set(target, New<String>("createSession").ToLocalChecked(), GetFunction(New<FunctionTemplate>(create_session)).ToLocalChecked());
	Nan::Set(target, New<String>("setTimeout").ToLocalChecked(), GetFunction(New<FunctionTemplate>(set_timeout)).ToLocalChecked());
	
    Session::Init(target);
}

NODE_MODULE(tohsync , Init)

