/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "exception.h"
#include "hdfs.h" /* for hdfsFileInfo */
#include "hdfs_json_parser.h"

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <jansson.h>

static const char * const temporaryRedirectCode = "307 TEMPORARY_REDIRECT";
static const char * const twoHundredOKCode = "200 OK";
static const char * const twoHundredOneCreatedCode = "201 Created";
static const char * const httpHeaderString = "HTTP/1.1";

/**
 * Exception information after calling JSON operations
 */
struct jsonException {
  const char *exception;
  const char *javaClassName;
  const char *message;
};

static void dotsToSlashes(char *str)
{
    for (; *str != '\0'; str++) {
        if (*str == '.')
            *str = '/';
    }
}

/** Print out the JSON exception information */
static int printJsonExceptionV(struct jsonException *exc, int noPrintFlags,
                               const char *fmt, va_list ap)
{
    char *javaClassName = NULL;
    int excErrno = EINTERNAL, shouldPrint = 0;
    if (!exc) {
        fprintf(stderr, "printJsonExceptionV: the jsonException is NULL\n");
        return EINTERNAL;
    }
    javaClassName = strdup(exc->javaClassName);
    if (!javaClassName) {
        fprintf(stderr, "printJsonExceptionV: internal out of memory error\n");
        return EINTERNAL;
    }
    dotsToSlashes(javaClassName);
    getExceptionInfo(javaClassName, noPrintFlags, &excErrno, &shouldPrint);
    free(javaClassName);
    
    if (shouldPrint) {
        vfprintf(stderr, fmt, ap);
        fprintf(stderr, " error:\n");
        fprintf(stderr, "Exception: %s\nJavaClassName: %s\nMessage: %s\n",
                exc->exception, exc->javaClassName, exc->message);
    }
    
    free(exc);
    return excErrno;
}

/**
 * Print out JSON exception information.
 *
 * @param exc             The exception information to print and free
 * @param noPrintFlags    Flags which determine which exceptions we should NOT
 *                        print.
 * @param fmt             Printf-style format list
 * @param ...             Printf-style varargs
 *
 * @return                The POSIX error number associated with the exception
 *                        object.
 */
static int printJsonException(struct jsonException *exc, int noPrintFlags,
                              const char *fmt, ...)
{
    va_list ap;
    int ret = 0;
    
    va_start(ap, fmt);
    ret = printJsonExceptionV(exc, noPrintFlags, fmt, ap);
    va_end(ap);
    return ret;
}

/** Parse the exception information from JSON */
static struct jsonException *parseJsonException(json_t *jobj)
{
    const char *key = NULL;
    json_t *value = NULL;
    struct jsonException *exception = NULL;
    void *iter = NULL;
    
    exception = calloc(1, sizeof(*exception));
    if (!exception) {
        return NULL;
    }
    
    iter = json_object_iter(jobj);
    while (iter) {
        key = json_object_iter_key(iter);
        value = json_object_iter_value(iter);
        
        if (!strcmp(key, "exception")) {
            exception->exception = json_string_value(value);
        } else if (!strcmp(key, "javaClassName")) {
            exception->javaClassName = json_string_value(value);
        } else if (!strcmp(key, "message")) {
            exception->message = json_string_value(value);
        }
        
        iter = json_object_iter_next(jobj, iter);
    }
    return exception;
}

/** 
 * Parse the exception information which is presented in JSON
 * 
 * @param content   Exception information in JSON
 * @return          jsonException for printing out
 */
static struct jsonException *parseException(const char *content)
{
    json_error_t error;
    size_t flags = 0;
    const char *key = NULL;
    json_t *value;
    json_t *jobj;
    struct jsonException *exception = NULL;
    
    if (!content) {
        return NULL;
    }
    jobj = json_loads(content, flags, &error);
    if (!jobj) {
        fprintf(stderr, "JSon parsing error: on line %d: %s\n",
                error.line, error.text);
        return NULL;
    }
    void *iter = json_object_iter(jobj);
    while(iter)  {
        key = json_object_iter_key(iter);
        value = json_object_iter_value(iter);
        
        if (!strcmp(key, "RemoteException") &&
                    json_typeof(value) == JSON_OBJECT) {
            exception = parseJsonException(value);
            break;
        }
        iter = json_object_iter_next(jobj, iter);
    }
    
    json_decref(jobj);
    return exception;
}

/**
 * Parse the response information which uses TRUE/FALSE 
 * to indicate whether the operation succeeded
 *
 * @param response  Response information
 * @return          0 to indicate success
 */
static int parseBoolean(const char *response)
{
    json_t *root, *value;
    json_error_t error;
    size_t flags = 0;
    int result = 0;
    
    root = json_loads(response, flags, &error);
    if (!root) {
        fprintf(stderr, "JSon parsing error: on line %d: %s\n",
                error.line, error.text);
        return EIO;
    }
    void *iter = json_object_iter(root);
    value = json_object_iter_value(iter);
    if (json_typeof(value) == JSON_TRUE)  {
        result = 0;
    } else {
        result = EIO;  // FALSE means error in remote NN/DN
    }
    json_decref(root);
    return result;
}

int parseMKDIR(const char *response)
{
    return parseBoolean(response);
}

int parseRENAME(const char *response)
{
    return parseBoolean(response);
}

int parseDELETE(const char *response)
{
    return parseBoolean(response);
}

int parseSETREPLICATION(const char *response)
{
    return parseBoolean(response);
}

/**
 * Check the header of response to see if it's 200 OK
 * 
 * @param header    Header information for checking
 * @param content   Stores exception information if there are errors
 * @param operation Indicate the operation for exception printing
 * @return 0 for success
 */
static int checkHeader(const char *header, const char *content,
                       const char *operation)
{
    char *result = NULL;
    const char delims[] = ":";
    char *savepter;
    int ret = 0;
    
    if (!header || strncmp(header, "HTTP/", strlen("HTTP/"))) {
        return EINVAL;
    }
    if (!(strstr(header, twoHundredOKCode)) ||
       !(result = strstr(header, "Content-Length"))) {
        struct jsonException *exc = parseException(content);
        if (exc) {
            ret = printJsonException(exc, PRINT_EXC_ALL,
                                       "Calling WEBHDFS (%s)", operation);
        } else {
            ret = EIO;
        }
        return ret;
    }
    result = strtok_r(result, delims, &savepter);
    result = strtok_r(NULL, delims, &savepter);
    while (isspace(*result)) {
        result++;
    }
    // Content-Length should be equal to 0,
    // and the string should be "0\r\nServer"
    if (strncmp(result, "0\r\n", 3)) {
        ret = EIO;
    }
    return ret;
}

int parseCHMOD(const char *header, const char *content)
{
    return checkHeader(header, content, "CHMOD");
}

int parseCHOWN(const char *header, const char *content)
{
    return checkHeader(header, content, "CHOWN");
}

int parseUTIMES(const char *header, const char *content)
{
    return checkHeader(header, content, "SETTIMES");
}

/**
 * Check if the header contains correct information
 * ("307 TEMPORARY_REDIRECT" and "Location")
 * 
 * @param header    Header for parsing
 * @param content   Contains exception information 
 *                  if the remote operation failed
 * @param operation Specify the remote operation when printing out exception
 * @return 0 for success
 */
static int checkRedirect(const char *header,
                         const char *content, const char *operation)
{
    const char *locTag = "Location";
    int ret = 0, offset = 0;
    
    // The header must start with "HTTP/1.1"
    if (!header || strncmp(header, httpHeaderString,
                           strlen(httpHeaderString))) {
        return EINVAL;
    }
    
    offset += strlen(httpHeaderString);
    while (isspace(header[offset])) {
        offset++;
    }
    // Looking for "307 TEMPORARY_REDIRECT" in header
    if (strncmp(header + offset, temporaryRedirectCode,
                strlen(temporaryRedirectCode))) {
        // Process possible exception information
        struct jsonException *exc = parseException(content);
        if (exc) {
            ret = printJsonException(exc, PRINT_EXC_ALL,
                                     "Calling WEBHDFS (%s)", operation);
        } else {
            ret = EIO;
        }
        return ret;
    }
    // Here we just simply check if header contains "Location" tag,
    // detailed processing is in parseDnLoc
    if (!(strstr(header, locTag))) {
        ret = EIO;
    }
    return ret;
}

int parseNnWRITE(const char *header, const char *content)
{
    return checkRedirect(header, content, "Write(NameNode)");
}

int parseNnAPPEND(const char *header, const char *content)
{
    return checkRedirect(header, content, "Append(NameNode)");
}

/** 0 for success , -1 for out of range, other values for error */
int parseOPEN(const char *header, const char *content)
{
    int ret = 0, offset = 0;
    
    if (!header || strncmp(header, httpHeaderString,
                           strlen(httpHeaderString))) {
        return EINVAL;
    }
    
    offset += strlen(httpHeaderString);
    while (isspace(header[offset])) {
        offset++;
    }
    if (strncmp(header + offset, temporaryRedirectCode,
                strlen(temporaryRedirectCode)) ||
        !strstr(header, twoHundredOKCode)) {
        struct jsonException *exc = parseException(content);
        if (exc) {
            // If the exception is an IOException and it is because
            // the offset is out of the range, do not print out the exception
            if (!strcasecmp(exc->exception, "IOException") &&
                    strstr(exc->message, "out of the range")) {
                ret = -1;
            } else {
                ret = printJsonException(exc, PRINT_EXC_ALL,
                                       "Calling WEBHDFS (OPEN)");
            }
        } else {
            ret = EIO;
        }
    }
    return ret;
}

int parseDnLoc(char *content, char **dn)
{
    char *url = NULL, *dnLocation = NULL, *savepter, *tempContent;
    const char *prefix = "Location: http://";
    const char *prefixToRemove = "Location: ";
    const char *delims = "\r\n";
    
    tempContent = strdup(content);
    if (!tempContent) {
        return ENOMEM;
    }
    
    dnLocation = strtok_r(tempContent, delims, &savepter);
    while (dnLocation && strncmp(dnLocation, "Location:",
                                 strlen("Location:"))) {
        dnLocation = strtok_r(NULL, delims, &savepter);
    }
    if (!dnLocation) {
        return EIO;
    }
    
    while (isspace(*dnLocation)) {
        dnLocation++;
    }
    if (strncmp(dnLocation, prefix, strlen(prefix))) {
        return EIO;
    }
    url = strdup(dnLocation + strlen(prefixToRemove));
    if (!url) {
        return ENOMEM;
    }
    *dn = url;
    return 0;
}

int parseDnWRITE(const char *header, const char *content)
{
    int ret = 0;
    if (header == NULL || header[0] == '\0' ||
                         strncmp(header, "HTTP/", strlen("HTTP/"))) {
        return EINVAL;
    }
    if (!(strstr(header, twoHundredOneCreatedCode))) {
        struct jsonException *exc = parseException(content);
        if (exc) {
            ret = printJsonException(exc, PRINT_EXC_ALL,
                                     "Calling WEBHDFS (WRITE(DataNode))");
        } else {
            ret = EIO;
        }
    }
    return ret;
}

int parseDnAPPEND(const char *header, const char *content)
{
    int ret = 0;
    
    if (header == NULL || header[0] == '\0' ||
                         strncmp(header, "HTTP/", strlen("HTTP/"))) {
        return EINVAL;
    }
    if (!(strstr(header, twoHundredOKCode))) {
        struct jsonException *exc = parseException(content);
        if (exc) {
            ret = printJsonException(exc, PRINT_EXC_ALL,
                                     "Calling WEBHDFS (APPEND(DataNode))");
        } else {
            ret = EIO;
        }
    }
    return ret;
}

/**
 * Retrieve file status from the JSON object 
 *
 * @param jobj          JSON object for parsing, which contains 
 *                      file status information
 * @param fileStat      hdfsFileInfo handle to hold file status information
 * @return 0 on success
 */
static int parseJsonForFileStatus(json_t *jobj, hdfsFileInfo *fileStat)
{
    const char *key, *tempstr;
    json_t *value;
    void *iter = NULL;
    
    iter = json_object_iter(jobj);
    while (iter) {
        key = json_object_iter_key(iter);
        value = json_object_iter_value(iter);
        
        if (!strcmp(key, "accessTime")) {
            // json field contains time in milliseconds,
            // hdfsFileInfo is counted in seconds
            fileStat->mLastAccess = json_integer_value(value) / 1000;
        } else if (!strcmp(key, "blockSize")) {
            fileStat->mBlockSize = json_integer_value(value);
        } else if (!strcmp(key, "length")) {
            fileStat->mSize = json_integer_value(value);
        } else if (!strcmp(key, "modificationTime")) {
            fileStat->mLastMod = json_integer_value(value) / 1000;
        } else if (!strcmp(key, "replication")) {
            fileStat->mReplication = json_integer_value(value);
        } else if (!strcmp(key, "group")) {
            fileStat->mGroup = strdup(json_string_value(value));
            if (!fileStat->mGroup) {
                return ENOMEM;
            }
        } else if (!strcmp(key, "owner")) {
            fileStat->mOwner = strdup(json_string_value(value));
            if (!fileStat->mOwner) {
                return ENOMEM;
            }
        } else if (!strcmp(key, "pathSuffix")) {
            fileStat->mName = strdup(json_string_value(value));
            if (!fileStat->mName) {
                return ENOMEM;
            }
        } else if (!strcmp(key, "permission")) {
            tempstr = json_string_value(value);
            fileStat->mPermissions = (short) strtol(tempstr, NULL, 8);
        } else if (!strcmp(key, "type")) {
            tempstr = json_string_value(value);
            if (!strcmp(tempstr, "DIRECTORY")) {
                fileStat->mKind = kObjectKindDirectory;
            } else {
                fileStat->mKind = kObjectKindFile;
            }
        }
        // Go to the next key-value pair in the json object
        iter = json_object_iter_next(jobj, iter);
    }
    return 0;
}

int parseGFS(const char *response, hdfsFileInfo *fileStat, int printError)
{
    int ret = 0, printFlag;
    json_error_t error;
    size_t flags = 0;
    json_t *jobj, *value;
    const char *key;
    void *iter = NULL;
    
    if (!response || !fileStat) {
        return EIO;
    }
    jobj = json_loads(response, flags, &error);
    if (!jobj) {
        fprintf(stderr, "error while parsing json: on line %d: %s\n",
                error.line, error.text);
        return EIO;
    }
    iter = json_object_iter(jobj);
    key = json_object_iter_key(iter);
    value = json_object_iter_value(iter);
    if (json_typeof(value) == JSON_OBJECT) {
        if (!strcmp(key, "RemoteException")) {
            struct jsonException *exception = parseJsonException(value);
            if (exception) {
                if (printError) {
                    printFlag = PRINT_EXC_ALL;
                } else {
                    printFlag = NOPRINT_EXC_FILE_NOT_FOUND |
                                NOPRINT_EXC_ACCESS_CONTROL |
                                NOPRINT_EXC_PARENT_NOT_DIRECTORY;
                }
                ret = printJsonException(exception, printFlag,
                                         "Calling WEBHDFS GETFILESTATUS");
            } else {
                ret = EIO;
            }
        } else if (!strcmp(key, "FileStatus")) {
            ret = parseJsonForFileStatus(value, fileStat);
        } else {
            ret = EIO;
        }
        
    } else {
        ret = EIO;
    }
    
    json_decref(jobj);
    return ret;
}

/**
 * Parse the JSON array. Called to parse the result of 
 * the LISTSTATUS operation. Thus each element of the JSON array is 
 * a JSON object with the information of a file entry contained 
 * in the folder.
 *
 * @param jobj          The JSON array to be parsed
 * @param fileStat      The hdfsFileInfo handle used to 
 *                      store a group of file information
 * @param numEntries    Capture the number of files in the folder
 * @return              0 for success
 */
static int parseJsonArrayForFileStatuses(json_t *jobj, hdfsFileInfo **fileStat,
                                         int *numEntries)
{
    json_t *jvalue = NULL;
    int i = 0, ret = 0, arraylen = 0;
    hdfsFileInfo *fileInfo = NULL;
    
    arraylen = (int) json_array_size(jobj);
    if (arraylen > 0) {
        fileInfo = calloc(arraylen, sizeof(hdfsFileInfo));
        if (!fileInfo) {
            return ENOMEM;
        }
    }
    for (i = 0; i < arraylen; i++) {
        //Getting the array element at position i
        jvalue = json_array_get(jobj, i);
        if (json_is_object(jvalue)) {
            ret = parseJsonForFileStatus(jvalue, &fileInfo[i]);
            if (ret) {
                goto done;
            }
        } else {
            ret = EIO;
            goto done;
        }
    }
done:
    if (ret) {
        free(fileInfo);
    } else {
        *numEntries = arraylen;
        *fileStat = fileInfo;
    }
    return ret;
}

int parseLS(const char *response, hdfsFileInfo **fileStats, int *numOfEntries)
{
    int ret = 0;
    json_error_t error;
    size_t flags = 0;
    json_t *jobj, *value;
    const char *key;
    void *iter = NULL;
    
    if (!response || response[0] == '\0' || !fileStats) {
        return EIO;
    }
    jobj = json_loads(response, flags, &error);
    if (!jobj) {
        fprintf(stderr, "error while parsing json: on line %d: %s\n",
                error.line, error.text);
        return EIO;
    }
    
    iter = json_object_iter(jobj);
    key = json_object_iter_key(iter);
    value = json_object_iter_value(iter);
    if (json_typeof(value) == JSON_OBJECT) {
        if (!strcmp(key, "RemoteException")) {
            struct jsonException *exception = parseJsonException(value);
            if (exception) {
                ret = printJsonException(exception, PRINT_EXC_ALL,
                                         "Calling WEBHDFS GETFILESTATUS");
            } else {
                ret = EIO;
            }
        } else if (!strcmp(key, "FileStatuses")) {
            iter = json_object_iter(value);
            value = json_object_iter_value(iter);
            if (json_is_array(value)) {
                ret = parseJsonArrayForFileStatuses(value, fileStats,
                                                    numOfEntries);
            } else {
                ret = EIO;
            }
        } else {
            ret = EIO;
        }
    } else {
        ret = EIO;
    }
    
    json_decref(jobj);
    return ret;
}
