/**
 * @brief Converts a product ID in product path name
 * This function is the only one knowing the correspondance
 * between the products' IDs and the product path names.
 * @param product The product ID
 * @return The corresponding product path name
 */
JNIEXPORT jstring JNICALL
Java_com_parrot_arsdk_ardiscovery_ARDiscoveryService_nativeGetProductPathName (JNIEnv *env, jclass thizz, int product)
{
    char nativePathName[128];
    jstring jPathName = NULL;

    ARDISCOVERY_getProductPathName (product, nativePathName, sizeof(nativePathName));

    if (nativePathName != NULL)
    {
        jPathName = (*env)->NewStringUTF(env, nativePathName);
    }

    return jPathName;
}
eARDISCOVERY_PRODUCT ARDISCOVERY_getProductFromPathName(const char *name)
{
    uint8_t product = ARDISCOVERY_PRODUCT_MAX;
    size_t namelen;
    int i = 0;

    char buffer[256];

    if (name == NULL)
        return ARDISCOVERY_PRODUCT_MAX;

    namelen = strlen(name);
    for (i = 0; (product == ARDISCOVERY_PRODUCT_MAX) && (i < ARDISCOVERY_PRODUCT_MAX); i++)
    {
        ARDISCOVERY_getProductPathName(i, buffer, 256);
        if(namelen < strlen(buffer))
            continue;

        if(strncmp(name, buffer, strlen(buffer)) == 0)
            product = i;
    }

    return product;
}
eARDATATRANSFER_ERROR ARDATATRANSFER_DataDownloader_DownloadPudFiles(ARDATATRANSFER_Manager_t *manager, eARUTILS_ERROR *errorUtils)
{
    char remotePath[ARUTILS_FTP_MAX_PATH_SIZE];
    char remoteProduct[ARUTILS_FTP_MAX_PATH_SIZE];
    char localPath[ARUTILS_FTP_MAX_PATH_SIZE];
    char productPathName[ARUTILS_FTP_MAX_PATH_SIZE];
    eARUTILS_ERROR errorFtp = ARUTILS_OK;
    eARUTILS_ERROR error = ARUTILS_OK;
    char *productFtpList = NULL;
    uint32_t productFtpListLen = 0;
    char *dataFtpList = NULL;
    uint32_t dataFtpListLen = 0;
    const char *nextProduct = NULL;
    const char *nextData = NULL;
    const char *productName;
    int product;
    eARDATATRANSFER_ERROR result = ARDATATRANSFER_OK;

    ARSAL_PRINT(ARSAL_PRINT_DEBUG, ARDATATRANSFER_DATA_DOWNLOADER_TAG, "");

    if (manager == NULL)
    {
        result = ARDATATRANSFER_ERROR_BAD_PARAMETER;
    }

    if ((result == ARDATATRANSFER_OK) && (manager->dataDownloader == NULL))
    {
        result = ARDATATRANSFER_ERROR_NOT_INITIALIZED;
    }

    if ((result == ARDATATRANSFER_OK) && (manager->dataDownloader->isCanceled != 0))
    {
        result = ARDATATRANSFER_ERROR_CANCELED;
    }

    if (result == ARDATATRANSFER_OK)
    {
        if (error == ARUTILS_OK)
        {
            error = ARUTILS_Manager_Ftp_List(manager->dataDownloader->ftpDataManager, manager->dataDownloader->remoteDirectory, &productFtpList, &productFtpListLen);
        }

        product = 0;
        while ((error == ARUTILS_OK) && (product < ARDISCOVERY_PRODUCT_MAX) && (manager->dataDownloader->isCanceled == 0))
        {
            char lineDataProduct[ARUTILS_FTP_MAX_PATH_SIZE];
            ARDISCOVERY_getProductPathName(product, productPathName, sizeof(productPathName));
            nextProduct = NULL;
            productName = ARUTILS_Ftp_List_GetNextItem(productFtpList, &nextProduct, productPathName, 1, NULL, NULL, lineDataProduct, ARUTILS_FTP_MAX_PATH_SIZE);

            if ((productName != NULL) && strcmp(productName, productPathName) == 0)
            {
                char lineDataData[ARUTILS_FTP_MAX_PATH_SIZE];
                const char *fileName;

                strncpy(remoteProduct, manager->dataDownloader->remoteDirectory, ARUTILS_FTP_MAX_PATH_SIZE);
                remoteProduct[ARUTILS_FTP_MAX_PATH_SIZE - 1] = '\0';
                strncat(remoteProduct, ARDATATRANSFER_DATA_DOWNLOADER_FTP_ROOT "/", ARUTILS_FTP_MAX_PATH_SIZE - strlen(remoteProduct) - 1);
                strncat(remoteProduct, productPathName, ARUTILS_FTP_MAX_PATH_SIZE - strlen(remoteProduct) - 1);
                strncat(remoteProduct, "/" ARDATATRANSFER_DATA_DOWNLOADER_FTP_DATADOWNLOAD "/", ARUTILS_FTP_MAX_PATH_SIZE - strlen(remoteProduct) - 1);

                error = ARUTILS_Manager_Ftp_List(manager->dataDownloader->ftpDataManager, remoteProduct, &dataFtpList, &dataFtpListLen);

                // Resume downloading_ files loop
                nextData = NULL;
                while ((error == ARUTILS_OK)
                        && (manager->dataDownloader->isCanceled == 0)
                        && ((fileName = ARUTILS_Ftp_List_GetNextItem(dataFtpList, &nextData, ARDATATRANSFER_MANAGER_DOWNLOADER_DOWNLOADING_PREFIX, 0, NULL, NULL, lineDataData, ARUTILS_FTP_MAX_PATH_SIZE)) != NULL))
                {
                    if (ARDATATRANSFER_DataDownloader_CompareFileExtension(fileName, ARDATATRANSFER_DATA_DOWNLOADER_PUD_EXT) == 0)
                    {
                        char restoreName[ARUTILS_FTP_MAX_PATH_SIZE];

                        strncpy(remotePath, remoteProduct, ARUTILS_FTP_MAX_PATH_SIZE);
                        remotePath[ARUTILS_FTP_MAX_PATH_SIZE - 1] = '\0';
                        strncat(remotePath, fileName, ARUTILS_FTP_MAX_PATH_SIZE - strlen(remotePath) - 1);

                        strncpy(localPath, manager->dataDownloader->localDataDirectory, ARUTILS_FTP_MAX_PATH_SIZE);
                        localPath[ARUTILS_FTP_MAX_PATH_SIZE - 1] = '\0';
                        strncat(localPath, fileName, ARUTILS_FTP_MAX_PATH_SIZE - strlen(localPath) -1);

                        errorFtp = ARUTILS_Manager_Ftp_Get(manager->dataDownloader->ftpDataManager, remotePath, localPath, NULL, NULL, FTP_RESUME_TRUE);

                        if (errorFtp == ARUTILS_OK)
                        {
                            errorFtp = ARUTILS_Manager_Ftp_Delete(manager->dataDownloader->ftpDataManager, remotePath);

                            strncpy(restoreName, manager->dataDownloader->localDataDirectory, ARUTILS_FTP_MAX_PATH_SIZE);
                            restoreName[ARUTILS_FTP_MAX_PATH_SIZE - 1] = '\0';
                            strncat(restoreName, fileName + strlen(ARDATATRANSFER_MANAGER_DOWNLOADER_DOWNLOADING_PREFIX), ARUTILS_FTP_MAX_PATH_SIZE - strlen(restoreName) - 1);

                            errorFtp = ARUTILS_FileSystem_Rename(localPath, restoreName);
                        }

                        ARSAL_PRINT(ARSAL_PRINT_WARNING, ARDATATRANSFER_DATA_DOWNLOADER_TAG, "DOWNLOADED (DOWNLOADING) %s, errorFtp: %d", fileName, errorFtp);
                        if (manager->dataDownloader->fileCompletionCallback != NULL)
                        {
                            const char *fileNameSrc = fileName + strlen(ARDATATRANSFER_MANAGER_DOWNLOADER_DOWNLOADING_PREFIX);
                            manager->dataDownloader->fileCompletionCallback(manager->dataDownloader->fileCompletionArg ,fileNameSrc, (errorFtp == ARUTILS_OK) ? ARDATATRANSFER_OK : ARDATATRANSFER_ERROR_FTP);
                        }
                    }
                }

                // Newer files loop
                nextData = NULL;
                while ((error == ARUTILS_OK)
                        && (manager->dataDownloader->isCanceled == 0)
                        && ((fileName = ARUTILS_Ftp_List_GetNextItem(dataFtpList, &nextData, NULL, 0, NULL, NULL, lineDataData, ARUTILS_FTP_MAX_PATH_SIZE)) != NULL))
                {
                    if ((ARDATATRANSFER_DataDownloader_CompareFileExtension(fileName, ARDATATRANSFER_DATA_DOWNLOADER_PUD_EXT) == 0)
                            && (strncmp(fileName, ARDATATRANSFER_MANAGER_DOWNLOADER_DOWNLOADING_PREFIX, strlen(ARDATATRANSFER_MANAGER_DOWNLOADER_DOWNLOADING_PREFIX)) != 0))
                    {
                        char initialPath[ARUTILS_FTP_MAX_PATH_SIZE];
                        char restoreName[ARUTILS_FTP_MAX_PATH_SIZE];

                        strncpy(initialPath, remoteProduct, ARUTILS_FTP_MAX_PATH_SIZE);
                        initialPath[ARUTILS_FTP_MAX_PATH_SIZE - 1] = '\0';
                        strncat(initialPath, fileName, ARUTILS_FTP_MAX_PATH_SIZE - strlen(initialPath) - 1);

                        strncpy(remotePath, remoteProduct, ARUTILS_FTP_MAX_PATH_SIZE);
                        remotePath[ARUTILS_FTP_MAX_PATH_SIZE - 1] = '\0';
                        strncat(remotePath, ARDATATRANSFER_MANAGER_DOWNLOADER_DOWNLOADING_PREFIX, ARUTILS_FTP_MAX_PATH_SIZE - strlen(remotePath) - 1);
                        strncat(remotePath, fileName, ARUTILS_FTP_MAX_PATH_SIZE - strlen(remotePath) - 1);

                        strncpy(localPath, manager->dataDownloader->localDataDirectory, ARUTILS_FTP_MAX_PATH_SIZE);
                        localPath[ARUTILS_FTP_MAX_PATH_SIZE - 1] = '\0';
                        strncat(localPath, ARDATATRANSFER_MANAGER_DOWNLOADER_DOWNLOADING_PREFIX, ARUTILS_FTP_MAX_PATH_SIZE - strlen(localPath) - 1);
                        strncat(localPath, fileName, ARUTILS_FTP_MAX_PATH_SIZE - strlen(localPath) - 1);

                        errorFtp = ARUTILS_Manager_Ftp_Rename(manager->dataDownloader->ftpDataManager, initialPath, remotePath);

                        if (errorFtp == ARUTILS_OK)
                        {
                            errorFtp = ARUTILS_Manager_Ftp_Get(manager->dataDownloader->ftpDataManager, remotePath, localPath, NULL, NULL, FTP_RESUME_FALSE);
                        }

                        if (errorFtp == ARUTILS_OK)
                        {
                            errorFtp = ARUTILS_Manager_Ftp_Delete(manager->dataDownloader->ftpDataManager, remotePath);

                            strncpy(restoreName, manager->dataDownloader->localDataDirectory, ARUTILS_FTP_MAX_PATH_SIZE);
                            restoreName[ARUTILS_FTP_MAX_PATH_SIZE - 1] = '\0';
                            strncat(restoreName, fileName, ARUTILS_FTP_MAX_PATH_SIZE - strlen(restoreName) - 1);
                            errorFtp = ARUTILS_FileSystem_Rename(localPath, restoreName);
                        }

                        ARSAL_PRINT(ARSAL_PRINT_WARNING, ARDATATRANSFER_DATA_DOWNLOADER_TAG, "DOWNLOADED %s, errorFtp: %d", fileName, errorFtp);
                        if (manager->dataDownloader->fileCompletionCallback != NULL)
                        {
                            manager->dataDownloader->fileCompletionCallback(manager->dataDownloader->fileCompletionArg ,fileName, (errorFtp == ARUTILS_OK) ? ARDATATRANSFER_OK : ARDATATRANSFER_ERROR_FTP);
                        }
                    }
                }

                if (dataFtpList != NULL)
                {
                    free(dataFtpList);
                    dataFtpList = NULL;
                    dataFtpListLen = 0;
                }
            }
            product++;
        }

        if (productFtpList != NULL)
        {
            free(productFtpList);
            productFtpList = NULL;
            productFtpListLen = 0;
        }
    }

    if (errorUtils != NULL)
    {
        *errorUtils = error;
    }

    if (error != ARUTILS_OK)
    {
        result = ARDATATRANSFER_ERROR_FTP;
    }

    return result;
}
eARDATATRANSFER_ERROR ARDATATRANSFER_DataDownloader_GetAvailableFiles (ARDATATRANSFER_Manager_t *manager, long *filesNumber)
{
    eARDATATRANSFER_ERROR result = ARDATATRANSFER_OK;
    eARUTILS_ERROR error = ARUTILS_OK;
    char productPathName[ARUTILS_FTP_MAX_PATH_SIZE];
    char remoteProduct[ARUTILS_FTP_MAX_PATH_SIZE];
    char *productFtpList = NULL;
    uint32_t productFtpListLen = 0;
    char *dataFtpList = NULL;
    uint32_t dataFtpListLen = 0;
    const char *nextProduct = NULL;
    const char *fileName;
    const char *nextData = NULL;
    int product;

    ARSAL_PRINT(ARSAL_PRINT_DEBUG, ARDATATRANSFER_DATA_DOWNLOADER_TAG, "");

    if ((manager == NULL) || (manager->dataDownloader == NULL) || (filesNumber == NULL))
    {
        result = ARDATATRANSFER_ERROR_BAD_PARAMETER;
    }
    else
    {
        *filesNumber = 0;
    }

    if (result == ARDATATRANSFER_OK)
    {
        error = ARUTILS_Manager_Ftp_List(manager->dataDownloader->ftpListManager, manager->dataDownloader->remoteDirectory, &productFtpList, &productFtpListLen);

        if (error != ARUTILS_OK)
        {
            result = ARDATATRANSFER_ERROR_FTP;
        }
    }

    product = 0;
    while ((result == ARDATATRANSFER_OK) && (product < ARDISCOVERY_PRODUCT_MAX))
    {
        char lineDataProduct[ARUTILS_FTP_MAX_PATH_SIZE];
        ARDISCOVERY_getProductPathName(product, productPathName, sizeof(productPathName));
        nextProduct = NULL;
        fileName = ARUTILS_Ftp_List_GetNextItem(productFtpList, &nextProduct, productPathName, 1, NULL, NULL, lineDataProduct, ARUTILS_FTP_MAX_PATH_SIZE);

        if ((fileName != NULL) && strcmp(fileName, productPathName) == 0)
        {
            char lineDataData[ARUTILS_FTP_MAX_PATH_SIZE];
            strncpy(remoteProduct, manager->dataDownloader->remoteDirectory, ARUTILS_FTP_MAX_PATH_SIZE);
            remoteProduct[ARUTILS_FTP_MAX_PATH_SIZE - 1] = '\0';
            strncat(remoteProduct, ARDATATRANSFER_DATA_DOWNLOADER_FTP_ROOT "/", ARUTILS_FTP_MAX_PATH_SIZE - strlen(remoteProduct) - 1);
            strncat(remoteProduct, productPathName, ARUTILS_FTP_MAX_PATH_SIZE - strlen(remoteProduct) - 1);
            strncat(remoteProduct, "/" ARDATATRANSFER_DATA_DOWNLOADER_FTP_DATADOWNLOAD "/", ARUTILS_FTP_MAX_PATH_SIZE - strlen(remoteProduct) - 1);

            error = ARUTILS_Manager_Ftp_List(manager->dataDownloader->ftpListManager, remoteProduct, &dataFtpList, &dataFtpListLen);

            if (error != ARUTILS_OK)
            {
                result = ARDATATRANSFER_ERROR_FTP;
            }

            nextData = NULL;
            while ((result == ARDATATRANSFER_OK)
                    && ((fileName = ARUTILS_Ftp_List_GetNextItem(dataFtpList, &nextData, NULL, 0, NULL, NULL, lineDataData, ARUTILS_FTP_MAX_PATH_SIZE)) != NULL))
            {
                // ARDATATRANSFER_MANAGER_DOWNLOADER_DOWNLOADING_PREFIX are also available
                if ((ARDATATRANSFER_DataDownloader_CompareFileExtension(fileName, ARDATATRANSFER_DATA_DOWNLOADER_PUD_EXT) == 0)
                        && (strncmp(fileName, ARDATATRANSFER_MANAGER_DOWNLOADER_PROCESSING_PREFIX, strlen(ARDATATRANSFER_MANAGER_DOWNLOADER_PROCESSING_PREFIX)) != 0))
                {
                    *filesNumber += 1;
                }
            }

            if (dataFtpList != NULL)
            {
                free(dataFtpList);
                dataFtpList = NULL;
                dataFtpListLen = 0;
            }
        }
        product++;
    }

    if (productFtpList != NULL)
    {
        free(productFtpList);
        productFtpList = NULL;
        productFtpListLen = 0;
    }

    return result;
}