// This is a generated file, modify: generate/templates/class_content.cc.
#include <nan.h>
#include <string.h>

extern "C" {
#include <git2.h>
}


#include "../include/functions/copy.h"
#include "../include/macros.h"
#include "../include/branch.h"

#include "../include/reference.h"
#include "../include/repository.h"
#include "../include/commit.h"
#include "../include/signature.h"
#include "../include/branch_iterator.h"

#include <iostream>

using namespace std;
using namespace v8;
using namespace node;


void GitBranch::InitializeComponent(Handle<v8::Object> target)
{
  NanScope();

  Local<Object> object = NanNew<Object>();

  NODE_SET_METHOD(object, "create", Create);
  NODE_SET_METHOD(object, "delete", Delete);
  NODE_SET_METHOD(object, "isHead", IsHead);
  NODE_SET_METHOD(object, "iteratorFree", IteratorFree);
  NODE_SET_METHOD(object, "iteratorNew", IteratorNew);
  NODE_SET_METHOD(object, "lookup", Lookup);
  NODE_SET_METHOD(object, "move", Move);
  NODE_SET_METHOD(object, "name", Name);
  NODE_SET_METHOD(object, "setUpstream", SetUpstream);
  NODE_SET_METHOD(object, "upstream", Upstream);

  target->Set(NanNew<String>("Branch"), object);
}


/*
  * @param Repository repo
   * @param String branch_name
   * @param Commit target
   * @param Number force
   * @param Signature signature
   * @param String log_message
    * @param Reference callback
   */
NAN_METHOD(GitBranch::Create)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsObject()) {
    return NanThrowError("Repository repo is required.");
  }

  if (args.Length() == 1 || !args[1]->IsString()) {
    return NanThrowError("String branch_name is required.");
  }

  if (args.Length() == 2 || !args[2]->IsObject()) {
    return NanThrowError("Commit target is required.");
  }

  if (args.Length() == 6 || !args[6]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  CreateBaton* baton = new CreateBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

// start convert_from_v8 block
  git_repository * from_repo;
  from_repo = ObjectWrap::Unwrap<GitRepository>(args[0]->ToObject())->GetValue();
// end convert_from_v8 block
  baton->repo = from_repo;
// start convert_from_v8 block
  const char * from_branch_name;

  String::Utf8Value branch_name(args[1]->ToString());
  from_branch_name = (const char *) strdup(*branch_name);
// end convert_from_v8 block
  baton->branch_name = from_branch_name;
// start convert_from_v8 block
  const git_commit * from_target;
  from_target = ObjectWrap::Unwrap<GitCommit>(args[2]->ToObject())->GetValue();
// end convert_from_v8 block
  baton->target = from_target;
// start convert_from_v8 block
  int from_force;

  if (args[3]->IsNumber()) {
    from_force = (int)   args[3]->ToNumber()->Value();
  } else {
    from_force = 0;
  }

// end convert_from_v8 block
  baton->force = from_force;
// start convert_from_v8 block
  const git_signature * from_signature;

  if (args[4]->IsObject()) {
    from_signature = ObjectWrap::Unwrap<GitSignature>(args[4]->ToObject())->GetValue();
  } else {
    from_signature = 0;
  }

// end convert_from_v8 block
  baton->signature = from_signature;
// start convert_from_v8 block
  const char * from_log_message;

  if (args[5]->IsString()) {

    String::Utf8Value log_message(args[5]->ToString());
    from_log_message = (const char *) strdup(*log_message);
  } else {
    from_log_message = 0;
  }

// end convert_from_v8 block
  baton->log_message = from_log_message;

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[6]));
  CreateWorker *worker = new CreateWorker(baton, callback);
  if (!args[0]->IsUndefined() && !args[0]->IsNull())
    worker->SaveToPersistent("repo", args[0]->ToObject());
  if (!args[1]->IsUndefined() && !args[1]->IsNull())
    worker->SaveToPersistent("branch_name", args[1]->ToObject());
  if (!args[2]->IsUndefined() && !args[2]->IsNull())
    worker->SaveToPersistent("target", args[2]->ToObject());
  if (!args[3]->IsUndefined() && !args[3]->IsNull())
    worker->SaveToPersistent("force", args[3]->ToObject());
  if (!args[4]->IsUndefined() && !args[4]->IsNull())
    worker->SaveToPersistent("signature", args[4]->ToObject());
  if (!args[5]->IsUndefined() && !args[5]->IsNull())
    worker->SaveToPersistent("log_message", args[5]->ToObject());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitBranch::CreateWorker::Execute()
{
  int result = git_branch_create(
                 &baton->out,baton->repo,baton->branch_name,baton->target,baton->force,baton->signature,baton->log_message    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitBranch::CreateWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitRefs baton->out
      to = GitRefs::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }

  free((void *)baton->branch_name);
  free((void *)baton->log_message);

  delete baton;
}

/*
 * @param Reference branch
     * @return Number  result    */
NAN_METHOD(GitBranch::Delete)
{
  NanEscapableScope();

  if (args.Length() == 0 || !args[0]->IsObject()) {
    return NanThrowError("Reference branch is required.");
  }

// start convert_from_v8 block
  git_reference * from_branch;
  from_branch = ObjectWrap::Unwrap<GitRefs>(args[0]->ToObject())->GetValue();
// end convert_from_v8 block
  int result = git_branch_delete(
                 from_branch
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
 * @param Reference branch
     * @return Number  result    */
NAN_METHOD(GitBranch::IsHead)
{
  NanEscapableScope();

  if (args.Length() == 0 || !args[0]->IsObject()) {
    return NanThrowError("Reference branch is required.");
  }

// start convert_from_v8 block
  const git_reference * from_branch;
  from_branch = ObjectWrap::Unwrap<GitRefs>(args[0]->ToObject())->GetValue();
// end convert_from_v8 block
  int result = git_branch_is_head(
                 from_branch
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
 * @param BranchIterator iter
     */
NAN_METHOD(GitBranch::IteratorFree)
{
  NanEscapableScope();

  if (args.Length() == 0 || !args[0]->IsObject()) {
    return NanThrowError("BranchIterator iter is required.");
  }

// start convert_from_v8 block
  git_branch_iterator * from_iter;
  from_iter = ObjectWrap::Unwrap<GitBranchIterator>(args[0]->ToObject())->GetValue();
// end convert_from_v8 block
  git_branch_iterator_free(
    from_iter
  );
  NanReturnUndefined();
}

/*
  * @param Repository repo
   * @param Number list_flags
    * @param BranchIterator callback
   */
NAN_METHOD(GitBranch::IteratorNew)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsObject()) {
    return NanThrowError("Repository repo is required.");
  }

  if (args.Length() == 1 || !args[1]->IsNumber()) {
    return NanThrowError("Number list_flags is required.");
  }

  if (args.Length() == 2 || !args[2]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  IteratorNewBaton* baton = new IteratorNewBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

// start convert_from_v8 block
  git_repository * from_repo;
  from_repo = ObjectWrap::Unwrap<GitRepository>(args[0]->ToObject())->GetValue();
// end convert_from_v8 block
  baton->repo = from_repo;
// start convert_from_v8 block
  git_branch_t from_list_flags;
  from_list_flags = (git_branch_t)  (int) args[1]->ToNumber()->Value();
// end convert_from_v8 block
  baton->list_flags = from_list_flags;

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[2]));
  IteratorNewWorker *worker = new IteratorNewWorker(baton, callback);
  if (!args[0]->IsUndefined() && !args[0]->IsNull())
    worker->SaveToPersistent("repo", args[0]->ToObject());
  if (!args[1]->IsUndefined() && !args[1]->IsNull())
    worker->SaveToPersistent("list_flags", args[1]->ToObject());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitBranch::IteratorNewWorker::Execute()
{
  int result = git_branch_iterator_new(
                 &baton->out,baton->repo,baton->list_flags    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitBranch::IteratorNewWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitBranchIterator baton->out
      to = GitBranchIterator::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }


  delete baton;
}

/*
  * @param Repository repo
   * @param String branch_name
   * @param Number branch_type
    * @param Reference callback
   */
NAN_METHOD(GitBranch::Lookup)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsObject()) {
    return NanThrowError("Repository repo is required.");
  }

  if (args.Length() == 1 || !args[1]->IsString()) {
    return NanThrowError("String branch_name is required.");
  }

  if (args.Length() == 2 || !args[2]->IsNumber()) {
    return NanThrowError("Number branch_type is required.");
  }

  if (args.Length() == 3 || !args[3]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  LookupBaton* baton = new LookupBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

// start convert_from_v8 block
  git_repository * from_repo;
  from_repo = ObjectWrap::Unwrap<GitRepository>(args[0]->ToObject())->GetValue();
// end convert_from_v8 block
  baton->repo = from_repo;
// start convert_from_v8 block
  const char * from_branch_name;

  String::Utf8Value branch_name(args[1]->ToString());
  from_branch_name = (const char *) strdup(*branch_name);
// end convert_from_v8 block
  baton->branch_name = from_branch_name;
// start convert_from_v8 block
  git_branch_t from_branch_type;
  from_branch_type = (git_branch_t)  (int) args[2]->ToNumber()->Value();
// end convert_from_v8 block
  baton->branch_type = from_branch_type;

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[3]));
  LookupWorker *worker = new LookupWorker(baton, callback);
  if (!args[0]->IsUndefined() && !args[0]->IsNull())
    worker->SaveToPersistent("repo", args[0]->ToObject());
  if (!args[1]->IsUndefined() && !args[1]->IsNull())
    worker->SaveToPersistent("branch_name", args[1]->ToObject());
  if (!args[2]->IsUndefined() && !args[2]->IsNull())
    worker->SaveToPersistent("branch_type", args[2]->ToObject());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitBranch::LookupWorker::Execute()
{
  int result = git_branch_lookup(
                 &baton->out,baton->repo,baton->branch_name,baton->branch_type    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitBranch::LookupWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitRefs baton->out
      to = GitRefs::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }

  free((void *)baton->branch_name);

  delete baton;
}

/*
  * @param Reference branch
   * @param String new_branch_name
   * @param Number force
   * @param Signature signature
   * @param String log_message
    * @param Reference callback
   */
NAN_METHOD(GitBranch::Move)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsObject()) {
    return NanThrowError("Reference branch is required.");
  }

  if (args.Length() == 1 || !args[1]->IsString()) {
    return NanThrowError("String new_branch_name is required.");
  }

  if (args.Length() == 2 || !args[2]->IsNumber()) {
    return NanThrowError("Number force is required.");
  }

  if (args.Length() == 3 || !args[3]->IsObject()) {
    return NanThrowError("Signature signature is required.");
  }

  if (args.Length() == 4 || !args[4]->IsString()) {
    return NanThrowError("String log_message is required.");
  }

  if (args.Length() == 5 || !args[5]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  MoveBaton* baton = new MoveBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

// start convert_from_v8 block
  git_reference * from_branch;
  from_branch = ObjectWrap::Unwrap<GitRefs>(args[0]->ToObject())->GetValue();
// end convert_from_v8 block
  baton->branch = from_branch;
// start convert_from_v8 block
  const char * from_new_branch_name;

  String::Utf8Value new_branch_name(args[1]->ToString());
  from_new_branch_name = (const char *) strdup(*new_branch_name);
// end convert_from_v8 block
  baton->new_branch_name = from_new_branch_name;
// start convert_from_v8 block
  int from_force;
  from_force = (int)   args[2]->ToNumber()->Value();
// end convert_from_v8 block
  baton->force = from_force;
// start convert_from_v8 block
  const git_signature * from_signature;
  from_signature = ObjectWrap::Unwrap<GitSignature>(args[3]->ToObject())->GetValue();
// end convert_from_v8 block
  baton->signature = from_signature;
// start convert_from_v8 block
  const char * from_log_message;

  String::Utf8Value log_message(args[4]->ToString());
  from_log_message = (const char *) strdup(*log_message);
// end convert_from_v8 block
  baton->log_message = from_log_message;

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[5]));
  MoveWorker *worker = new MoveWorker(baton, callback);
  if (!args[0]->IsUndefined() && !args[0]->IsNull())
    worker->SaveToPersistent("branch", args[0]->ToObject());
  if (!args[1]->IsUndefined() && !args[1]->IsNull())
    worker->SaveToPersistent("new_branch_name", args[1]->ToObject());
  if (!args[2]->IsUndefined() && !args[2]->IsNull())
    worker->SaveToPersistent("force", args[2]->ToObject());
  if (!args[3]->IsUndefined() && !args[3]->IsNull())
    worker->SaveToPersistent("signature", args[3]->ToObject());
  if (!args[4]->IsUndefined() && !args[4]->IsNull())
    worker->SaveToPersistent("log_message", args[4]->ToObject());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitBranch::MoveWorker::Execute()
{
  int result = git_branch_move(
                 &baton->out,baton->branch,baton->new_branch_name,baton->force,baton->signature,baton->log_message    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitBranch::MoveWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitRefs baton->out
      to = GitRefs::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }

  free((void *)baton->new_branch_name);
  free((void *)baton->log_message);

  delete baton;
}

/*
  * @param Reference ref
    * @param String callback
   */
NAN_METHOD(GitBranch::Name)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsObject()) {
    return NanThrowError("Reference ref is required.");
  }

  if (args.Length() == 1 || !args[1]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  NameBaton* baton = new NameBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

// start convert_from_v8 block
  const git_reference * from_ref;
  from_ref = ObjectWrap::Unwrap<GitRefs>(args[0]->ToObject())->GetValue();
// end convert_from_v8 block
  baton->ref = from_ref;

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[1]));
  NameWorker *worker = new NameWorker(baton, callback);
  if (!args[0]->IsUndefined() && !args[0]->IsNull())
    worker->SaveToPersistent("ref", args[0]->ToObject());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitBranch::NameWorker::Execute()
{
  int result = git_branch_name(
                 &baton->out,baton->ref    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitBranch::NameWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block
    if (baton->out) {
      to = NanNew<String>(baton->out);
    } else {
      to = NanNull();
    }

    // end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }

  free((void *)baton->out);

  delete baton;
}

/*
 * @param Reference branch
   * @param String upstream_name
     * @return Number  result    */
NAN_METHOD(GitBranch::SetUpstream)
{
  NanEscapableScope();

  if (args.Length() == 0 || !args[0]->IsObject()) {
    return NanThrowError("Reference branch is required.");
  }

// start convert_from_v8 block
  git_reference * from_branch;
  from_branch = ObjectWrap::Unwrap<GitRefs>(args[0]->ToObject())->GetValue();
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_upstream_name;

  if (args[1]->IsString()) {

    String::Utf8Value upstream_name(args[1]->ToString());
    from_upstream_name = (const char *) strdup(*upstream_name);
  } else {
    from_upstream_name = 0;
  }

// end convert_from_v8 block
  int result = git_branch_set_upstream(
                 from_branch
                 ,from_upstream_name
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
  * @param Reference branch
     * @return Reference out    */
NAN_METHOD(GitBranch::Upstream)
{
  NanEscapableScope();

  if (args.Length() == 0 || !args[0]->IsObject()) {
    return NanThrowError("Reference branch is required.");
  }

  git_reference * out = 0;
// start convert_from_v8 block
  const git_reference * from_branch;
  from_branch = ObjectWrap::Unwrap<GitRefs>(args[0]->ToObject())->GetValue();
// end convert_from_v8 block
  int result = git_branch_upstream(
                 &out
                 ,from_branch
               );
  if (result != GIT_OK) {

    if (giterr_last()) {
      return NanThrowError(giterr_last()->message);
    } else {
      return NanThrowError("Unknown Error");
    }
  }

  Handle<Value> to;
// start convert_to_v8 block

  if (out != NULL) {
    // GitRefs out
    to = GitRefs::New((void *)out, false);
  } else {
    to = NanNull();
  }

// end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}
Persistent<Function> GitBranch::constructor_template;
