#include "Global.h"
#include "Exception.h"
#include "__mysql.h"
#include <iostream>
#include <stdlib.h>

namespace jet {

   Global::Global(char **envp) : envp(envp) {
      
   }

   Global::~Global() {

   }

   void Global::dump() {
      for (auto i = variables.begin(); i != variables.end(); i++)
	std::cout << i->first << "=[" << i->second << "]" << std::endl; 
   }

   bool Global::sessionExists(coreutils::MString sessionId) {
      return sessions.find(sessionId) != sessions.end();
   }
   
   void Global::addSession(coreutils::MString sessionId, __mysql *mysql) {
      if(sessionExists(sessionId))
	coreutils::Exception("sessionid already exists.");
      sessions[sessionId] = mysql;
   }
   
   void Global::removeSession(coreutils::MString sessionId) {
      sessions.erase(sessionId);
   }
         
   __mysql * Global::getSession(coreutils::MString sessionId) {
      if(sessions.find(sessionId) == sessions.end())
	throw coreutils::Exception("requested session is not available.");
      return sessions[sessionId];
   }
   
   coreutils::ZString Global::getSessionVariable(coreutils::MString &splitName) {      
      if(sessions.find(splitName[0]) == sessions.end())
	throw coreutils::Exception("requested session is not available in variable.");
      return sessions[splitName[0]]->getColumnValue(splitName[1]);
   }

   void Global::outputHeaders() {
      if(headers.size() > 0) {	
	 for(auto header = headers.begin();
	     header != headers.end();
	     ++header) {
	    std::cout << header->first << ": " << header->second << std::endl;
	 }
	 std::cout << std::endl;
      }   
   }

   void Global::setupFormData(coreutils::ZString &formdata) {      
      coreutils::ZString boundary = formdata.goeol();
      while(!formdata.eod()) {
	 if(formdata.ifNext("Content-Disposition: form-data;")) {
	    formdata.skipWhitespace();
	    if(formdata.ifNext("name=\"")) {
	       coreutils::ZString name = formdata.getTokenInclude("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-");
	       if(formdata.ifNext("\"")) {
		  formdata.goeol();
		  formdata.goeol();
		  coreutils::ZString data = formdata.getTokenExclude("-"); // TODO: Fix this parsing. Need a string exclusion method to check for 'boundary'.
		  data.trimCRLF();
		  formdata.ifNext(boundary);
		  int index = 0;
		  coreutils::MString namex;
		  do {
		     namex = "";
		     namex << name << ":" << index++;
		  } while(cgiVariables.count(namex) != 0);		  
		  cgiVariables[namex] = data;		  
		  if(formdata.ifNext("--"))
		    break;
		  formdata.goeol();
	       }
	       else
		 throw coreutils::Exception("expecting closing double quote on variable name in received CGI data.");
	    } else
	      throw coreutils::Exception("expecting name subfield in received CGI data.");
	 } else
	   throw coreutils::Exception("expecting Content-Disposition header in received CGI data.");
      }	 
   }

   void Global::setupFormURLEncoded(coreutils::ZString &formdata) {      
      while(!formdata.eod()) {
	 coreutils::ZString name = formdata.getTokenInclude("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-");
	 if(formdata.ifNext("=")) {
	    coreutils::MString data = formdata.getTokenExclude("&");
	    formdata.ifNext("&");
	    int index = 0;
	    coreutils::MString namex;
	    do {
	       namex = "";
	       namex << name << ":" << index++;
	    } while(cgiVariables.count(namex) != 0);	    
	    cgiVariables[namex] = data.fromCGI();		  
	 } else
	   throw coreutils::Exception("expecting = after name in received CGI data.");
      }	 
   }
   
}
