//#define ENABLE_CORS_SUPER_FUN_TIME
#include "http-server.h"
#include "../server.h" //FIM_BUFFER_LEN

uint16_t intLen(uint16_t i) {
    if(i >= 10000) return 5;
    if(i >= 1000)  return 4;
    if(i >= 100)   return 3;
    if(i >= 10)    return 2;
    /*(i >= 1) */  return 1;
}

char * responseHeader(int docLen, int *outLen) {
    static char buf[2048];
    char dateBuf[2048], saved[2][2048], *fmt = TYPICAL_HEADER;
    time_t n;
    struct tm *t;

    // save the previous locale and timezone
    strcpy(saved[0], setlocale(LC_ALL, NULL)); strcpy(saved[1], tzname[0]);
    // update locale to "C" (English day/month names are required by HTTP)
    setlocale(LC_ALL, "C");
    // set the timezone to Greenwich Mean Time as per RFC7231 7.1.1.2
    setenv("TZ", "GMT", 1); tzset();
    // get the current time
    n = time(NULL);
    // split the time into parts (seconds, minutes, ..., day-in-the-year)
    t = gmtime(&n);
    /*  copy the time into our buffer, using this format:
     *         %a: abbreviated name of day
     *         | ,: a comma
     *         | | %d: day of month as decimal 01-31
     *         | | |   %b: abbreviated month name
     *         | | |   |   %Y: Year as decimal includes century
     *         | | |   |   |   %H: 24-hour clock decimal 00-23
     *         | | |   |   |   |
     *  Date: Tue, 11 Aug 2020 15:29:59 GMT
     *                            |  |   |
     *      minute decimal 00-59: %M |   |
     *         second decimal 00-59: %S  |
     *                         timezone: %Z
     *
     *  [!] all four white spaces are required, the total lenght should always
     *      be exactly 29 characters long
     */
    strftime(dateBuf, sizeof(dateBuf), "%a, %d %b %Y %H:%M:%S %Z", t);
    // generate a warning message when we goof up the Date header
    if(RFC7231_DATE_LENGTH != strlen(dateBuf))
        fprintf(stderr, "[!] bug - a date that does not match http/1.1"
            "rules was generated\ninvalid date: [%s] should be %zu characters"
            "long but is not\n", dateBuf, strlen(dateBuf));
    // restore the locale and timezone
    setlocale(LC_ALL, saved[0]);
    strcpy(tzname[0], saved[1]); setenv("TZ", tzname[0], 1); tzset();
    // store the header in a contiguous buffer
    snprintf(buf, 2048, fmt, dateBuf, docLen);
    #ifdef PRINT_HTTP_HEADER
    // send http response to stderr
    fprintf(stderr, buf);
    #endif
    // set output length
    *outLen = strlen(buf);
    return buf;
}

char *httpEcho(char *s, int len, int *limit) {
    int headerLen, prediction;
    char *p, *buf, *header, *out = "Hola! You sent: ";
    /*  for http responses to fit inside of a fixed length buffer we may need
     *  to limit "echo" responses because of overhead from the http header
     *  contents and our own canned text, unfortunately we cannot easily and
     *  precisely say what that limit is due to the http header having
     *  a variable lenght header, (Content-Length)
     *  Most HTTP servers limit this header to 8K, meaning that 1-4 decimal
     *  digits can be used to represent lengths between 0 and 8000.
     *
     *  predict the header length, then reduce len if needed to fit into
     *  server.h FIM_BUFFER_LEN by multiplying each occurence of a printf format
     *  substitution symbol by two, and subtracting the result from the length
     *  of http-server.c response header format template length (TYPICAL_HEADER)
     *  then add in the length of the date header and the number of digits
     *  needed to represent the length of the message body subtract this total
     *  from FIM_BUFFER_LEN -- this is just a prediction, after truncating length,
     *  the number of digits needed to represent the new length could be fewer
     */
    prediction = (sizeof(TYPICAL_HEADER) - 1) - (2 * TYPICAL_HEADER_FORMAT_SUBSTITUTIONS);
    prediction += (RFC7231_DATE_LENGTH + intLen(len + strlen(out)));
    prediction = (FIM_BUFFER_LEN - prediction);
    // also remove the length required for canned text
    prediction -= strlen(out);
    // shorten the echoed part of the response when buffer limit would be reached
    if(prediction >= len); else {
        fprintf(stderr, "buffer can only fit %d of %d characters for the "
            "response to client\n", prediction, len);
        len = 0 < prediction ?prediction :0;
    }
    // get the response headers
    header = responseHeader(strlen(out) + len, &headerLen);
    // do not send too much data to the client
    if((0 < headerLen) && (300 > headerLen)); else {
        fprintf(stderr, "Why the weird amount of data?"
            "headerLen [%d]\n"
            "client data length [%d]\n"
            "my hola length [%zu]\n", headerLen, len, strlen(out));
        return out;
    }
    if(0) fprintf(stderr, "webpage length: head %d + server %zu + body %d = %zu\n",
        headerLen, strlen(out), len,
        strlen(out) + len + headerLen);
    // report the length of buffer for caller
    *limit = strlen(out) + len + headerLen;
    // generate a larger buffer
    buf = (char *) malloc(strlen(out) + len + headerLen);
    // make a copy of the pointer so we can copy data
    p = buf;
    // copy the header
    for(uint32_t i = headerLen; i--;) *p++ = *header++;
    // copy the canned out message
    for(uint32_t i = strlen(out); i--;) *p++ = *out++;
    // copy the client message
    for(uint32_t i = len; i--;) *p++ = *s++;
    return buf;
}
