#ifndef GITREPOSITORY_H
#define GITREPOSITORY_H
// generated from class_header.h
#include <nan.h>
#include <string>

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

#include "../include/config.h"
#include "../include/repository.h"
#include "../include/signature.h"
#include "../include/reference.h"
#include "../include/index.h"
#include "../include/repository_init_options.h"
#include "../include/odb.h"
#include "../include/refdb.h"
#include "../include/oid.h"
// Forward declaration.
struct git_repository {
};

using namespace node;
using namespace v8;

class GitRepository : public ObjectWrap {
public:

  static Persistent<Function> constructor_template;
  static void InitializeComponent (Handle<v8::Object> target);

  git_repository *GetValue();
  git_repository **GetRefValue();

  static Handle<Value> New(void *raw, bool selfFreeing);
  bool selfFreeing;

private:
  GitRepository(git_repository *raw, bool selfFreeing);
  ~GitRepository();

  static NAN_METHOD(JSNewFunction);


  struct ConfigBaton {
    int error_code;
    const git_error* error;
    git_config * out;
    git_repository * repo;
  };
  class ConfigWorker : public NanAsyncWorker {
  public:
    ConfigWorker(
      ConfigBaton *_baton,
      NanCallback *callback
    ) : NanAsyncWorker(callback)
      , baton(_baton) {};
    ~ConfigWorker() {};
    void Execute();
    void HandleOKCallback();

  private:
    ConfigBaton *baton;
  };

  static NAN_METHOD(Config);

  struct ConfigSnapshotBaton {
    int error_code;
    const git_error* error;
    git_config * out;
    git_repository * repo;
  };
  class ConfigSnapshotWorker : public NanAsyncWorker {
  public:
    ConfigSnapshotWorker(
      ConfigSnapshotBaton *_baton,
      NanCallback *callback
    ) : NanAsyncWorker(callback)
      , baton(_baton) {};
    ~ConfigSnapshotWorker() {};
    void Execute();
    void HandleOKCallback();

  private:
    ConfigSnapshotBaton *baton;
  };

  static NAN_METHOD(ConfigSnapshot);

  static NAN_METHOD(DetachHead);

  static NAN_METHOD(GetNamespace);

  struct HeadBaton {
    int error_code;
    const git_error* error;
    git_reference * out;
    git_repository * repo;
  };
  class HeadWorker : public NanAsyncWorker {
  public:
    HeadWorker(
      HeadBaton *_baton,
      NanCallback *callback
    ) : NanAsyncWorker(callback)
      , baton(_baton) {};
    ~HeadWorker() {};
    void Execute();
    void HandleOKCallback();

  private:
    HeadBaton *baton;
  };

  static NAN_METHOD(Head);

  static NAN_METHOD(HeadDetached);

  static NAN_METHOD(HeadUnborn);

  struct IndexBaton {
    int error_code;
    const git_error* error;
    git_index * out;
    git_repository * repo;
  };
  class IndexWorker : public NanAsyncWorker {
  public:
    IndexWorker(
      IndexBaton *_baton,
      NanCallback *callback
    ) : NanAsyncWorker(callback)
      , baton(_baton) {};
    ~IndexWorker() {};
    void Execute();
    void HandleOKCallback();

  private:
    IndexBaton *baton;
  };

  static NAN_METHOD(Index);

  struct InitBaton {
    int error_code;
    const git_error* error;
    git_repository * out;
    const char * path;
    unsigned int is_bare;
  };
  class InitWorker : public NanAsyncWorker {
  public:
    InitWorker(
      InitBaton *_baton,
      NanCallback *callback
    ) : NanAsyncWorker(callback)
      , baton(_baton) {};
    ~InitWorker() {};
    void Execute();
    void HandleOKCallback();

  private:
    InitBaton *baton;
  };

  static NAN_METHOD(Init);

  struct InitExtBaton {
    int error_code;
    const git_error* error;
    git_repository * out;
    const char * repo_path;
    git_repository_init_options * opts;
  };
  class InitExtWorker : public NanAsyncWorker {
  public:
    InitExtWorker(
      InitExtBaton *_baton,
      NanCallback *callback
    ) : NanAsyncWorker(callback)
      , baton(_baton) {};
    ~InitExtWorker() {};
    void Execute();
    void HandleOKCallback();

  private:
    InitExtBaton *baton;
  };

  static NAN_METHOD(InitExt);

  static NAN_METHOD(InitInitOptions);

  static NAN_METHOD(IsBare);

  static NAN_METHOD(IsEmpty);

  static NAN_METHOD(IsShallow);

  static NAN_METHOD(MessageRemove);

  struct OdbBaton {
    int error_code;
    const git_error* error;
    git_odb * out;
    git_repository * repo;
  };
  class OdbWorker : public NanAsyncWorker {
  public:
    OdbWorker(
      OdbBaton *_baton,
      NanCallback *callback
    ) : NanAsyncWorker(callback)
      , baton(_baton) {};
    ~OdbWorker() {};
    void Execute();
    void HandleOKCallback();

  private:
    OdbBaton *baton;
  };

  static NAN_METHOD(Odb);

  struct OpenBaton {
    int error_code;
    const git_error* error;
    git_repository * out;
    const char * path;
  };
  class OpenWorker : public NanAsyncWorker {
  public:
    OpenWorker(
      OpenBaton *_baton,
      NanCallback *callback
    ) : NanAsyncWorker(callback)
      , baton(_baton) {};
    ~OpenWorker() {};
    void Execute();
    void HandleOKCallback();

  private:
    OpenBaton *baton;
  };

  static NAN_METHOD(Open);

  struct OpenBareBaton {
    int error_code;
    const git_error* error;
    git_repository * out;
    const char * bare_path;
  };
  class OpenBareWorker : public NanAsyncWorker {
  public:
    OpenBareWorker(
      OpenBareBaton *_baton,
      NanCallback *callback
    ) : NanAsyncWorker(callback)
      , baton(_baton) {};
    ~OpenBareWorker() {};
    void Execute();
    void HandleOKCallback();

  private:
    OpenBareBaton *baton;
  };

  static NAN_METHOD(OpenBare);

  struct OpenExtBaton {
    int error_code;
    const git_error* error;
    git_repository * out;
    const char * path;
    unsigned int flags;
    const char * ceiling_dirs;
  };
  class OpenExtWorker : public NanAsyncWorker {
  public:
    OpenExtWorker(
      OpenExtBaton *_baton,
      NanCallback *callback
    ) : NanAsyncWorker(callback)
      , baton(_baton) {};
    ~OpenExtWorker() {};
    void Execute();
    void HandleOKCallback();

  private:
    OpenExtBaton *baton;
  };

  static NAN_METHOD(OpenExt);

  static NAN_METHOD(Path);

  struct RefdbBaton {
    int error_code;
    const git_error* error;
    git_refdb * out;
    git_repository * repo;
  };
  class RefdbWorker : public NanAsyncWorker {
  public:
    RefdbWorker(
      RefdbBaton *_baton,
      NanCallback *callback
    ) : NanAsyncWorker(callback)
      , baton(_baton) {};
    ~RefdbWorker() {};
    void Execute();
    void HandleOKCallback();

  private:
    RefdbBaton *baton;
  };

  static NAN_METHOD(Refdb);

  static NAN_METHOD(SetHead);

  static NAN_METHOD(SetHeadDetached);

  static NAN_METHOD(SetNamespace);

  static NAN_METHOD(SetWorkdir);

  static NAN_METHOD(State);

  static NAN_METHOD(StateCleanup);

  static NAN_METHOD(Workdir);

  struct WrapOdbBaton {
    int error_code;
    const git_error* error;
    git_repository * out;
    git_odb * odb;
  };
  class WrapOdbWorker : public NanAsyncWorker {
  public:
    WrapOdbWorker(
      WrapOdbBaton *_baton,
      NanCallback *callback
    ) : NanAsyncWorker(callback)
      , baton(_baton) {};
    ~WrapOdbWorker() {};
    void Execute();
    void HandleOKCallback();

  private:
    WrapOdbBaton *baton;
  };

  static NAN_METHOD(WrapOdb);
  git_repository *raw;
};

#endif
