#include "common.h"
#include "Base.h"

bool CGI::Base::initialize() {
    nRequests = 0;
    tStart = ::time(0);
    pid = ::getpid();
    const char* sDirectory = ::getenv("RECORD_TO");
    if (!sDirectory) {
        sDirectory = ::getenv("TEMP");
        if (!sDirectory) {
            sDirectory = "/tmp";
        }
    }
    sRecordDirectory = sDirectory;
    sRecordDirectory.strcat("/");
    ::mkdir(sRecordDirectory,0777);
    const char* s = ::getenv("RECORD_ON");
    wantRecord = (s && *s && (0 < atoi(s)));
    fRequest = ::fopen("/dev/null","r");
    fResponse = ::fopen("/dev/null","w");
    return true;
}

extern char** environ;

static int countEnviron() {
    int n = 0;
    for (; environ[n]; ++n) {
    }
    return n;
}

static int compareEnviron(const void* a,const void* b) {
    const char* s1 = *(const char**)a;
    const char* s2 = *(const char**)b;
    int v = ::strcmp(s1,s2);
    //printf("compare '%s' to '%s' returns %d\n",s1,s2,v);
    return v;
}

static void sortEnviron() {
    int n = countEnviron();
    ::qsort(environ,n,sizeof(char*),compareEnviron);
}

void CGI::Base::writeResponse(FILE* f) {
    fprintf(f,"Content-Type: text/html\n\n<html><title>CGI %s</title><h3>CGI %s</h3>",getName(),getName());
    fprintf(f,"<table border=1 cellspacing=0 cellpadding=4><tr><th>argument<th>value\n");
    fprintf(f,"</table>\n");
    fprintf(f,"<h4>environment values</h4>\n<pre>");
    sortEnviron();
    for (int i = 0; environ[i]; ++i) {
        fprintf(f,"%s\n",environ[i]);
    }
    fprintf(f,"</pre>\n");
    if (!sScriptFilename) {
        fprintf(f,"<p>SCRIPT_FILENAME not set.</p>\n");
    } else {
        fprintf(f,"<p>Could not run script: '%s'</p>\n",sScriptFilename);
        if (0 < ::strlen(sLastError)) {
            fprintf(f,"<code>%s</code>\n",sLastError.getBuffer());
        }
    }
}

void CGI::Base::handleRequest() {
    sLastError = "";
    sScriptFilename = ::getenv("SCRIPT_FILENAME");
    if (!sScriptFilename) {
        writeResponse(fResponse);
        nameRecord();
        recordResponse();
        fprintf(fResponse,"<p>SCRIPT_FILENAME not set.</p>\n");
        return;
    }
    if (!runScript()) {
        writeResponse(fResponse);
    }
    if (wantRecord) {
        nameRecord();
        recordResponse();
    }
}

void CGI::Base::nameRecord() {
    ++nRequests;
    time_t t = time(0);
    struct tm* p = ::localtime(&t);
    static const char sFormat[] = "%sCGI.%04d-%02d-%02d-%02d-%02d-%02d.%08lx.%d.log";
    int n = ::strlen(sRecordDirectory) + ::strlen(sFormat) + 10;
    sprintf(sRecordName.getBuffer(n),sFormat, //
            sRecordDirectory.getBuffer(), //
            1900 + p->tm_year, //
            1 + p->tm_mon, //
            p->tm_mday, //
            p->tm_hour, //
            p->tm_min, //
            p->tm_sec, //
            (long) pid,nRequests);
}

void CGI::Base::recordResponse() {
    fprintf(fResponse,"<p>recorded to: '%s'</p>\n",sRecordName.getBuffer());
    FILE* log = fopen(sRecordName,"w");
    if (!log) {
        fprintf(fResponse,"<p>error: '%s'</p>\n",::strerror(errno));
        return;
    }
    writeResponse(log);
    fclose(log);
}

bool CGI::Base::runScript() {
    return false;
}