#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>

#include "nebclient.h"
#include "tap.h"

#define neb_ok(server, ...) \
    if (!ok(__VA_ARGS__)) { \
        diag("nebErr: %s", nebErr(server)); \
    }

#define tst_nebFree(foo) \
    if (foo) nebFree(foo)

int main (int argc, char **argv) {
    nebServer       *server = NULL;
    char            *key = "foobarbaz";

    plan_tests(24);

    if (getenv("NEB_SERVER")) {
        server = nebServerAlloc(getenv("NEB_SERVER"));
    } else {
        server = nebServerAlloc(NULL);
    }
    ok(server, "server not NULL");

    printf("# server set to %s\n", server->endpoint);

    {
        char        *URI = NULL;
        char        *filename;
       
        filename = nebCreate(server, key, NULL, &URI);
        diag("filename is %s", filename);
        neb_ok(server, filename, "create object");
        ok(URI, "URI not NULL");
        neb_ok(server, nebDelete(server, key), "delete object");

        tst_nebFree(URI);
        tst_nebFree(filename);
    }

    {
        char        *URI = NULL;
        int         fh;
       
        fh = nebOpenCreate(server, key, NULL, &URI);

        neb_ok(server, fh > -1, "create new object filehandle");
        ok(URI, "URI not NULL");

        tst_nebFree(URI);
        close(fh);
    }

    {
        int         fh;

        fh = nebOpen(server, key, NEB_READ);
        diag("fh is %d", fh);

        neb_ok(server, fh > 0, "open object for reading");

        close(fh);
    }

    {
        int         fh;

        fh = nebOpen(server, key, NEB_WRITE);
        diag("fh is %d", fh);

        neb_ok(server, fh > 0, "open object for writing");

        close(fh);
    }


    neb_ok(server, nebReplicate(server, key, NULL, NULL), "replicate object");

    neb_ok(server, nebOpen(server, key, NEB_WRITE) < 0, "write to object with multiple instances");

    neb_ok(server, nebCull(server, key), "cull object");

    neb_ok(server, nebStat(server, key), "stat object");

    neb_ok(server, nebLock(server, key, NEB_WRITE), "lock object write");
    neb_ok(server, nebUnlock(server, key, NEB_WRITE), "unlock object write");

    neb_ok(server, nebLock(server, key, NEB_READ), "lock object read");
    neb_ok(server, nebUnlock(server, key, NEB_READ), "unlock object read");

    neb_ok(server, nebSetXattr(server, key, "user.copies", "2",  NEB_CREATE), "set user.copies xattr");

    {
        nebObjectInstances *locations = NULL;

        locations = nebFindInstances(server, key, NULL);

        neb_ok(server, locations, "locations not NULL");
        ok(locations && locations->n == 1, "find instances");

        nebObjectInstancesFree(locations);
    }

    {
        char        *filename = NULL;
       
        filename = nebFind(server, key);

        neb_ok(server, filename, "find file name");

        tst_nebFree(filename);
    }


    neb_ok(server, nebCopy(server, key, "copyiedfile"), "copy object");

    neb_ok(server, nebSwap(server, key, "copyiedfile"), "swap objects");

    neb_ok(server, nebDelete(server, key), "delete object");

    neb_ok(server, nebMove(server, "copyiedfile", "movedfile"), "move object");

    if (!nebDelete(server, "movedfile")) {
        diag( "cleanup failed %s\n", nebErr(server));
    }

    nebServerFree(server);

    return exit_status();
}
