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

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

#include "../include/functions/copy.h"
#include "../include/attr.h"

#include "../include/repository.h"

using namespace v8;
using namespace node;

void GitAttr::Initialize(Handle<v8::Object> target) {
  NanScope();

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

        NODE_SET_METHOD(object, "get", Get);
            NODE_SET_METHOD(object, "getMany", GetMany);
                  NODE_SET_METHOD(object, "cacheFlush", CacheFlush);
            NODE_SET_METHOD(object, "addMacro", AddMacro);
      
  target->Set(NanNew<String>("Attr"), object);
}

            /**
        * @param Repository repo
            * @param Uint32 flags
            * @param String path
            * @param String name
            * @param String callback
  */
NAN_METHOD(GitAttr::Get) {
  NanScope();
              if (args.Length() == 0 || !args[0]->IsObject()) {
      return NanThrowError("Repository repo is required.");
    }
                if (args.Length() == 1 || !args[1]->IsNumber()) {
      return NanThrowError("Uint32 flags is required.");
    }
                if (args.Length() == 2 || !args[2]->IsString()) {
      return NanThrowError("String path is required.");
    }
                if (args.Length() == 3 || !args[3]->IsString()) {
      return NanThrowError("String name is required.");
    }
      
  if (args.Length() == 4 || !args[4]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  GetBaton* baton = new GetBaton;
  baton->error_code = GIT_OK;
  baton->error = NULL;
                      git_repository * from_repo;
          from_repo = ObjectWrap::Unwrap<GitRepository>(args[0]->ToObject())->GetValue();
  
            baton->repo = from_repo;
                                  uint32_t from_flags;
          from_flags = (uint32_t)   args[1]->ToNumber()->Value();
  
            baton->flags = from_flags;
                                  const char * from_path;
          String::Utf8Value path(args[2]->ToString());
      from_path = (const char *) strdup(*path);
  
            baton->path = from_path;
                                  const char * from_name;
          String::Utf8Value name(args[3]->ToString());
      from_name = (const char *) strdup(*name);
  
            baton->name = from_name;
                    
  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[4]));
  GetWorker *worker = new GetWorker(baton, callback);
                    if (!args[0]->IsUndefined() && !args[0]->IsNull())
    worker->SaveToPersistent("repo", args[0]->ToObject());
                        if (!args[1]->IsUndefined() && !args[1]->IsNull())
    worker->SaveToPersistent("flags", args[1]->ToObject());
                        if (!args[2]->IsUndefined() && !args[2]->IsNull())
    worker->SaveToPersistent("path", args[2]->ToObject());
                        if (!args[3]->IsUndefined() && !args[3]->IsNull())
    worker->SaveToPersistent("name", args[3]->ToObject());
            
  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitAttr::GetWorker::Execute() {
    int result = git_attr_get(
                    &baton->value_out,    
              baton->repo,    
              baton->flags,    
              baton->path,    
              baton->name    
        );

    baton->error_code = result;

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

  }

void GitAttr::GetWorker::HandleOKCallback() {
  TryCatch try_catch;
  if (baton->error_code == GIT_OK) {
        Handle<Value> to;
                      to = NanNew<String>(baton->value_out);
  
                          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->value_out);
                                    free((void *)baton->path);
                        free((void *)baton->name);
            
  delete baton;
}
                  /**
        * @param Repository repo
            * @param Uint32 flags
            * @param String path
            * @param Number num_attr
            * @param String names
            * @param String callback
  */
NAN_METHOD(GitAttr::GetMany) {
  NanScope();
              if (args.Length() == 0 || !args[0]->IsObject()) {
      return NanThrowError("Repository repo is required.");
    }
                if (args.Length() == 1 || !args[1]->IsNumber()) {
      return NanThrowError("Uint32 flags is required.");
    }
                if (args.Length() == 2 || !args[2]->IsString()) {
      return NanThrowError("String path is required.");
    }
                if (args.Length() == 3 || !args[3]->IsUint32()) {
      return NanThrowError("Number num_attr is required.");
    }
                if (args.Length() == 4 || !args[4]->IsString()) {
      return NanThrowError("String names is required.");
    }
      
  if (args.Length() == 5 || !args[5]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  GetManyBaton* baton = new GetManyBaton;
  baton->error_code = GIT_OK;
  baton->error = NULL;
                      git_repository * from_repo;
          from_repo = ObjectWrap::Unwrap<GitRepository>(args[0]->ToObject())->GetValue();
  
            baton->repo = from_repo;
                                  uint32_t from_flags;
          from_flags = (uint32_t)   args[1]->ToNumber()->Value();
  
            baton->flags = from_flags;
                                  const char * from_path;
          String::Utf8Value path(args[2]->ToString());
      from_path = (const char *) strdup(*path);
  
            baton->path = from_path;
                                  size_t from_num_attr;
          from_num_attr = (size_t)   args[3]->ToUint32()->Value();
  
            baton->num_attr = from_num_attr;
                                  const char ** from_names;
          String::Utf8Value names(args[4]->ToString());
      from_names = (const char **) strdup(*names);
  
            baton->names = from_names;
                    
  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[5]));
  GetManyWorker *worker = new GetManyWorker(baton, callback);
                    if (!args[0]->IsUndefined() && !args[0]->IsNull())
    worker->SaveToPersistent("repo", args[0]->ToObject());
                        if (!args[1]->IsUndefined() && !args[1]->IsNull())
    worker->SaveToPersistent("flags", args[1]->ToObject());
                        if (!args[2]->IsUndefined() && !args[2]->IsNull())
    worker->SaveToPersistent("path", args[2]->ToObject());
                        if (!args[3]->IsUndefined() && !args[3]->IsNull())
    worker->SaveToPersistent("num_attr", args[3]->ToObject());
                        if (!args[4]->IsUndefined() && !args[4]->IsNull())
    worker->SaveToPersistent("names", args[4]->ToObject());
            
  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitAttr::GetManyWorker::Execute() {
    int result = git_attr_get_many(
                    &baton->values_out,    
              baton->repo,    
              baton->flags,    
              baton->path,    
              baton->num_attr,    
              baton->names    
        );

    baton->error_code = result;

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

  }

void GitAttr::GetManyWorker::HandleOKCallback() {
  TryCatch try_catch;
  if (baton->error_code == GIT_OK) {
        Handle<Value> to;
                      to = NanNew<String>(baton->values_out);
  
                          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->values_out);
                                    free((void *)baton->path);
                              free((void *)baton->names);
            
  delete baton;
}
                    /**
      * @param Repository repo
      */
NAN_METHOD(GitAttr::CacheFlush) {
  NanScope();
            if (args.Length() == 0 || !args[0]->IsObject()) {
      return NanThrowError("Repository repo is required.");
    }
      
  
                      git_repository * from_repo;
          from_repo = ObjectWrap::Unwrap<GitRepository>(args[0]->ToObject())->GetValue();
  
              
git_attr_cache_flush(
          from_repo
            );

  

  NanReturnUndefined();
}
                  /**
      * @param Repository repo
            * @param String name
            * @param String values
            * @return Int32 result  */
NAN_METHOD(GitAttr::AddMacro) {
  NanScope();
            if (args.Length() == 0 || !args[0]->IsObject()) {
      return NanThrowError("Repository repo is required.");
    }
                if (args.Length() == 1 || !args[1]->IsString()) {
      return NanThrowError("String name is required.");
    }
                if (args.Length() == 2 || !args[2]->IsString()) {
      return NanThrowError("String values is required.");
    }
      
  
                      git_repository * from_repo;
          from_repo = ObjectWrap::Unwrap<GitRepository>(args[0]->ToObject())->GetValue();
  
                                  const char * from_name;
          String::Utf8Value name(args[1]->ToString());
      from_name = (const char *) strdup(*name);
  
                                  const char * from_values;
          String::Utf8Value values(args[2]->ToString());
      from_values = (const char *) strdup(*values);
  
              
  int result = git_attr_add_macro(
          from_repo
        ,          from_name
        ,          from_values
            );

          free((void *)from_name);
              free((void *)from_values);
      

  Handle<Value> to;
          to = NanNew<Number>(result);
            NanReturnValue(to);
  }
      

Persistent<Function> GitAttr::constructor_template;
