/* ----------------------------------------------
*/
#include "adoublehelper.h"
#include "afpcmd.h"
#include "afphelper.h"
#include "testhelper.h"

static char temp[MAXPATHLEN];
static char temp1[MAXPATHLEN];

STATIC void test136()
{
    int dir;
    char *name  = "t136 move, rename ";
    char *name1 = "t136 dir/new file name";
    char *name2 = "new file name";
    char *ndir  = "t136 dir";
    uint16_t vol = VolID;
    unsigned int ret;
    ENTER_TEST

    if (Path[0] == '\0') {
        test_skipped(T_PATH);
        goto test_exit;
    }

    FAIL(FPCreateFile(Conn, vol, 0, DIRDID_ROOT, name))
    sprintf(temp, "%s/%s", Path, ndir);

    if (!Quiet) {
        fprintf(stdout, "mkdir(%s)\n", temp);
    }

    if (mkdir(temp, 0777)) {
        if (!Quiet) {
            fprintf(stdout, "\tFAILED mkdir %s %s\n", temp, strerror(errno));
        }

        test_failed();
    }

    /* Workaround for musl mkdir() not setting the right permissions */
    if (chmod(temp, 0777)) {
        test_failed();
    }

    ret = FPMoveAndRename(Conn, vol, DIRDID_ROOT, DIRDID_ROOT, name, name1);

    if (not_valid(ret, AFPERR_MISC, AFPERR_PARAM)) {
        test_failed();
    }

    dir = get_did(Conn, vol, DIRDID_ROOT, ndir);
    FAIL(FPMoveAndRename(Conn, vol, DIRDID_ROOT, dir, name, name2))
    FAIL(FPDelete(Conn, vol, DIRDID_ROOT, name1))
    FAIL(!FPDelete(Conn, vol, DIRDID_ROOT, name))
    FAIL(FPDelete(Conn, vol, dir, ""))
test_exit:
    exit_test("FPMoveAndRename:test136: move and rename in a dir without .AppleDouble");
}

/* ----------------------- */
STATIC void test137()
{
    int fork;
    int dir;
    uint16_t bitmap = 0;
    char *name  = "t137 move, rename ";
    char *name1 = "t137 dir/new file name";
    char *name2 = "new file name";
    char *ndir  = "t137 dir";
    uint16_t vol = VolID;
    unsigned int ret;
    ENTER_TEST

    if (Path[0] == '\0') {
        test_skipped(T_PATH);
        goto test_exit;
    }

    FAIL(FPCreateFile(Conn, vol, 0, DIRDID_ROOT, name))
    sprintf(temp, "%s/%s", Path, ndir);

    if (!Quiet) {
        fprintf(stdout, "mkdir(%s)\n", temp);
    }

    if (mkdir(temp, 0777)) {
        if (!Quiet) {
            fprintf(stdout, "\tFAILED mkdir %s %s\n", temp, strerror(errno));
        }

        test_failed();
    }

    /* Workaround for musl mkdir() not setting the right permissions */
    if (chmod(temp, 0777)) {
        test_failed();
    }

    fork = FPOpenFork(Conn, vol, OPENFORK_RSCS, bitmap, DIRDID_ROOT, name,
                      OPENACC_WR | OPENACC_RD);

    if (!fork) {
        test_failed();
    }

    ret = FPMoveAndRename(Conn, vol, DIRDID_ROOT, DIRDID_ROOT, name, name1);

    if (not_valid(ret, AFPERR_MISC, AFPERR_PARAM)) {
        test_failed();
    }

    dir = get_did(Conn, vol, DIRDID_ROOT, ndir);
    FAIL(FPMoveAndRename(Conn, vol, DIRDID_ROOT, dir, name, name2))
    FAIL(fork && FPCloseFork(Conn, fork))
    FAIL(FPDelete(Conn, vol, DIRDID_ROOT, name1))
    FAIL(!FPDelete(Conn, vol, DIRDID_ROOT, name))
    FAIL(FPDelete(Conn, vol, dir, ""))
test_exit:
    exit_test("FPMoveAndRename:test137: move and rename open file in dir without .AppleDouble");
}

/* -------------------------- */
STATIC void test139()
{
    int  dir;
    char *name = "t139 file";
    char *name1 = "t139 dir";
    uint16_t vol = VolID;
    ENTER_TEST

    if (Path[0] == '\0') {
        test_skipped(T_PATH);
        goto test_exit;
    }

    if (!(dir = FPCreateDir(Conn, vol, DIRDID_ROOT, name1))) {
        test_nottested();
        goto test_exit;
    }

    FAIL(FPCreateFile(Conn, vol, 0, DIRDID_ROOT, name))
    delete_unix_md(Path, "", name);
    FAIL(FPMoveAndRename(Conn, vol, DIRDID_ROOT, dir, name, ""))
    FAIL(FPDelete(Conn, vol, dir, name))
    FAIL(!FPDelete(Conn, vol, DIRDID_ROOT, name))
    FAIL(FPDelete(Conn, vol, dir, ""))
test_exit:
    exit_test("FPMoveAndRename:test139: Move And Rename");
}

/* ------------------------- */
STATIC void test302()
{
    char *name = "t302 dir";
    char *name1 = "t302 file";
    char *name2 = "t302 file1";
    int dir;
    uint16_t vol = VolID;
    int id;
    int id1;
    ENTER_TEST

    if (Path[0] == '\0') {
        test_skipped(T_PATH);
        goto test_exit;
    }

    if (!(dir = FPCreateDir(Conn, vol, DIRDID_ROOT, name))) {
        test_nottested();
        goto test_exit;
    }

    FAIL(FPCreateFile(Conn, vol, 0, dir, name1))
    id = get_fid(Conn, vol, dir, name1);

    if (adouble == AD_V2) {
        if (rename_unix_file(Path, name, name1, name2) < 0) {
            if (!Quiet) {
                fprintf(stdout, "\tFAILED unable to rename \"%s/%s/%s\" to \"%s\" :%s\n", Path,
                        name, name1, name2, strerror(errno));
            }

            test_failed();
            goto fin;
        }
    } else {
        sprintf(temp, "%s/%s/%s", Path, name, name1);
        sprintf(temp1, "%s/%s/%s", Path, name, name2);

        if (rename(temp, temp1) < 0) {
            if (!Quiet) {
                fprintf(stdout, "\tFAILED unable to rename \"%s\" to \"%s\" :%s\n", temp, temp1,
                        strerror(errno));
            }

            test_failed();
            goto fin;
        }
    }

    id1 = get_fid(Conn, vol, dir, name2);

    if (id != id1) {
        if (!Quiet) {
            fprintf(stdout, "\tNOTE id are not the same %d %d\n", ntohl(id), ntohl(id1));
        }

        test_failed();
    }

fin:
    FAIL(FPDelete(Conn, vol, dir, name2))
    FAIL(FPDelete(Conn, vol, DIRDID_ROOT, name))
test_exit:
    exit_test("FPMoveAndRename:test302: file renamed by someone else, cnid updated");
}

/* ------------------------- */
STATIC void test323()
{
    char *name  = "t323 dir";
    char *name1 = "t323 dir1";
    char *file = "t323 file";
    int  dir1, dir;
    uint16_t bitmap = (1 << FILPBIT_FNUM);
    uint16_t vol = VolID;
    ENTER_TEST

    if (Path[0] == '\0') {
        test_skipped(T_PATH);
        goto test_exit;
    }

    if (!(dir = FPCreateDir(Conn, vol, DIRDID_ROOT, name))) {
        test_nottested();
        goto test_exit;
    }

    if (!(dir1 = FPCreateDir(Conn, vol, DIRDID_ROOT, name1))) {
        test_failed();
        goto fin;
    }

    FAIL(FPCreateFile(Conn, vol, 0, dir, file))
    FAIL(FPCreateFile(Conn, vol, 0, dir1, file))
    bitmap = (1 << FILPBIT_LNAME) | (1 << FILPBIT_FNUM);
    FAIL(FPGetFileDirParams(Conn, vol, dir, file, bitmap, 0))
    FAIL(FPGetFileDirParams(Conn, vol, dir1, file, bitmap, 0))
    sprintf(temp, "%s/%s/%s", Path, name, file);
    sprintf(temp1, "%s/%s/%s", Path, name1, file);

    if (!Quiet) {
        fprintf(stdout, "rename %s --> %s\n", temp, temp1);
    }

    if (rename(temp, temp1) < 0) {
        if (!Quiet) {
            fprintf(stdout, "\tFAILED unable to rename %s to %s :%s\n", temp, temp1,
                    strerror(errno));
        }

        test_failed();
    }

    bitmap = (1 << FILPBIT_LNAME) | (1 << FILPBIT_FNUM);
    FAIL(FPGetFileDirParams(Conn, vol, dir1, file, bitmap, 0))
fin:
    FAIL(FPDelete(Conn, vol, dir1, file))
    FPDelete(Conn, vol, dir, file);
    FAIL(FPDelete(Conn, vol, dir, ""))
    FAIL(FPDelete(Conn, vol, dir1, ""))
test_exit:
    exit_test("FPGetFileDirParms:test323: file moved with cnid not updated");
}

/* ------------------------- */
STATIC void test365()
{
    char *name  = "t365 in";
    char *name1 = "t365 out";
    char *file = "t365 file";
    int  dir1, dir;
    uint16_t bitmap = (1 << FILPBIT_FNUM);
    uint16_t vol = VolID;
    ENTER_TEST

    if (Path[0] == '\0') {
        test_skipped(T_PATH);
        goto test_exit;
    }

    if (!(dir = FPCreateDir(Conn, vol, DIRDID_ROOT, name))) {
        test_nottested();
        goto test_exit;
    }

    if (!(dir1 = FPCreateDir(Conn, vol, DIRDID_ROOT, name1))) {
        test_failed();
        goto fin;
    }

    FAIL(FPCreateFile(Conn, vol, 0, dir, file))
    bitmap = (1 << FILPBIT_LNAME) | (1 << FILPBIT_FNUM);
    FAIL(FPGetFileDirParams(Conn, vol, dir, file, bitmap, 0))
    sprintf(temp, "%s/%s/%s", Path, name, file);
    sprintf(temp1, "%s/%s/%s", Path, name1, file);

    if (!Quiet) {
        fprintf(stdout, "rename %s --> %s\n", temp, temp1);
    }

    if (rename(temp, temp1) < 0) {
        if (!Quiet) {
            fprintf(stdout, "\tFAILED unable to rename %s to %s :%s\n", temp, temp1,
                    strerror(errno));
        }

        test_failed();
    }

    if (adouble == AD_V2) {
        sprintf(temp, "%s/%s/.AppleDouble/%s", Path, name, file);
        sprintf(temp1, "%s/%s/.AppleDouble/%s", Path, name1, file);

        if (!Quiet) {
            fprintf(stdout, "rename %s --> %s\n", temp, temp1);
        }

        if (rename(temp, temp1) < 0) {
            if (!Quiet) {
                fprintf(stdout, "\tFAILED unable to rename %s to %s :%s\n", temp, temp1,
                        strerror(errno));
            }

            test_failed();
        }
    }

    bitmap = (1 << FILPBIT_LNAME) | (1 << FILPBIT_FNUM);
    FAIL(FPGetFileDirParams(Conn, vol, dir1, file, bitmap, 0))
fin:
    FAIL(FPDelete(Conn, vol, dir1, file))
    FPDelete(Conn, vol, dir, file);
    FAIL(FPDelete(Conn, vol, dir, ""))
    FAIL(FPDelete(Conn, vol, dir1, ""))
test_exit:
    exit_test("FPGetFileDirParms:test365: file moved with cnid not updated");
}

/* ----------- */
void T2FPMoveAndRename_test()
{
    ENTER_TESTSET
    test136();
    test137();
    test139();
    test302();
    test323();
    test365();
}
