

#include "./service_file.h"
#include "aqhome-cgi/modules/mroot.h"
#include "aqhome-cgi/modules/common/madmin.h"
#include "aqhome-cgi/modules/common/mmodules.h"
#include "aqhome-cgi/modules/common/musers.h"
#include "aqhome-cgi/modules/devices/mdevices.h"
#include "aqhome/aqhome.h"

#include <aqcgi/cgi.h>
#include <aqcgi/request.h>
#include <aqdiagram/aqdiagram.h>

#include <gwenhywfar/gwenhywfar.h>
#include <gwenhywfar/nogui.h>
#include <gwenhywfar/logger.h>
#include <gwenhywfar/text.h>
#include <gwenhywfar/debug.h>

#include <string.h>
#include <errno.h>
#include <stdio.h>


#define AQHOME_CGI_LOGFILE "/var/www/aqhome-cgi/log/aqhome-cgi.log"

#define AQHOME_CGI_DEFAULT_STATIC_FILES  AQHOME_CGI_WWWDIR"/static"
#define AQHOME_CGI_DEFAULT_RUNTIME_FILES AQHOME_CGI_WWWDIR"/data"
#define AQHOME_CGI_DEFAULT_CACHE_FILES   AQHOME_CGI_WWWDIR"/cache"
#define AQHOME_CGI_DEFAULT_BASE_URL      "http://127.0.0.1/aqbt"
#define AQHOME_CGI_DEFAULT_LOGLEVEL      "warning"


/* ------------------------------------------------------------------------------------------------
 * forward declarations
 * ------------------------------------------------------------------------------------------------
 */

static void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles, const char *sBaseUrl);
static int _handlePath(AQCGI_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles);
static void logStart(void);
static int _init(const char *sPathRuntimeFiles, const char *sBaseUrl);



/* ------------------------------------------------------------------------------------------------
 * code
 * ------------------------------------------------------------------------------------------------
 */

int main(int argc, char **argv)
{
  GWEN_GUI *gui;
  const char *sPathStaticFiles;
  const char *sPathRuntimeFiles;
  const char *sBaseUrl;
  const char *sLogLevel;
  int logLevel;

  sLogLevel=getenv("AQHOME_LOGLEVEL");
  if (!(sLogLevel && *sLogLevel))
    sLogLevel=AQHOME_CGI_DEFAULT_LOGLEVEL;
  logLevel=GWEN_Logger_Name2Level(sLogLevel);

  sPathStaticFiles=getenv("AQHOME_STATIC_FILES");
  if (!(sPathStaticFiles && *sPathStaticFiles))
    sPathStaticFiles=AQHOME_CGI_DEFAULT_STATIC_FILES;

  sPathRuntimeFiles=getenv("AQHOME_RUNTIME_FILES");
  if (!(sPathRuntimeFiles && *sPathRuntimeFiles))
    sPathRuntimeFiles=AQHOME_CGI_DEFAULT_RUNTIME_FILES;

  sBaseUrl=getenv("AQHOME_BASE_URL");
  if (!(sBaseUrl && *sBaseUrl))
    sBaseUrl=AQHOME_CGI_DEFAULT_BASE_URL;

  GWEN_Init();
  gui=GWEN_NoGui_new();
  GWEN_Gui_SetGui(gui);

  logStart();
  GWEN_Logger_Open(GWEN_LOGDOMAIN, "gwenhywfar", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
  GWEN_Logger_Open(AQH_LOGDOMAIN, "aqhome", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
  GWEN_Logger_Open(AQCGI_LOGDOMAIN, "aqcgi", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
  GWEN_Logger_Open(AQDG_LOGDOMAIN, "aqdiagram", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);
  GWEN_Logger_Open(NULL, "aqhome-cgi", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);

  GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, logLevel);
  GWEN_Logger_SetLevel(AQCGI_LOGDOMAIN, logLevel);
  GWEN_Logger_SetLevel(NULL, logLevel);

  GWEN_Logger_Close(GWEN_LOGDOMAIN);
  GWEN_Logger_Open(GWEN_LOGDOMAIN, "gwenhywfar", AQHOME_CGI_LOGFILE, GWEN_LoggerType_File, GWEN_LoggerFacility_Daemon);

  GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, logLevel);
  GWEN_Logger_SetLevel(AQCGI_LOGDOMAIN, logLevel);
  GWEN_Logger_SetLevel(AQDG_LOGDOMAIN, logLevel);
  GWEN_Logger_SetLevel(NULL, logLevel);

  if (argc>1 && argv[1]) {
    if (0==strcasecmp(argv[1], "init")) {
      int rv;

      rv=_init(sPathRuntimeFiles, sBaseUrl);
      if (rv<0) {
	fprintf(stderr, "Error on init (%d)\n", rv);
	return 2;
      }

    }
  }
  else {
    AQCGI_REQUEST *rq;

    DBG_ERROR(NULL, "Init CGI");
    AQCGI_Init();
    rq=AQCGI_ReadRequest();
    if (rq) {
      _handleRequest(rq, sPathStaticFiles, sPathRuntimeFiles, sBaseUrl);
    }
    else {
      fprintf(stdout, "Content-type: text/plain\n\n");
      fprintf(stdout, "Error: No Request!\n");
    }
    AQCGI_Fini();
  }

  return 0;
}



void _handleRequest(AQCGI_REQUEST *rq, const char *sPathStaticFiles, const char *sPathRuntimeFiles, const char *sBaseUrl)
{
  AQCGI_SERVICE *sv;
  int rv;

  sv=AQH_ServiceFiles_new(sPathRuntimeFiles, sBaseUrl);
  AQCGI_Service_SetLoginUrl(sv, "/aqhome/login");

  rv=_handlePath(sv, rq, sPathStaticFiles);
  if (rv<0) {
    DBG_INFO(NULL, "here (%d)", rv);
  }
  AQCGI_Service_free(sv);
}



int _handlePath(AQCGI_SERVICE *sv, AQCGI_REQUEST *rq, const char *sPathStaticFiles)
{
  AQCGI_MODULE *mRoot;
  AQCGI_MODULE *mParent;
  AQCGI_SESSION *session;
  const GWEN_STRINGLIST *sl;

  mRoot=AQH_ModRoot_new(sv, sPathStaticFiles);
  mParent=mRoot;
  session=AQH_ModService_ReadSession(mRoot, rq);
  AQH_ModService_CalcSessionModPerms(mRoot, session);

  sl=AQCGI_Request_GetStringlistPath(rq);
  if (sl) {
    GWEN_STRINGLISTENTRY *se;

    se=GWEN_StringList_FirstEntry(sl);
    while(se) {
      GWEN_STRINGLISTENTRY *seNext;
      const char *s;

      seNext=GWEN_StringListEntry_Next(se);
      s=GWEN_StringListEntry_Data(se);
       if (s && *s) {
	if (seNext) {
	  AQCGI_MODULE *m;

	  DBG_ERROR(NULL, "Entry: %s (%s)", s, seNext?"not last":"last");
	  m=AQH_ModService_LoadSubModule(mParent, rq, session, s);
          if (m==NULL) {
            AQCGI_Session_free(session);
	    AQCGI_Module_free(mRoot);
	    return GWEN_ERROR_GENERIC;
	  }
	  mParent=m;
	}
	else {
	  int rv;

	  /* last, let module handle remaining part */
          DBG_ERROR(NULL, "Entry: %s (last)", s);
	  rv=AQH_ModService_HandleRequest(mParent, rq, session, s);
	  if (rv<0) {
	    DBG_INFO(NULL, "here (%d)", rv);
            AQCGI_Session_free(session);
	    AQCGI_Module_free(mRoot);
	    return rv;
	  }
	  break;
	}
      }

      se=seNext;
    }
    AQCGI_Session_free(session);
    AQCGI_Module_free(mRoot);
    return 0;
  }
  else {
    AQCGI_Session_free(session);
    AQCGI_Module_free(mRoot);
    return GWEN_ERROR_GENERIC;
  }
}



void logStart()
{
  FILE *f;

  f=fopen(AQHOME_CGI_LOGFILE, "a+");
  if (f!=NULL) {
    fprintf(f, "Started.\n");
    fclose(f);
  }
}



int _init(const char *sPathRuntimeFiles, const char *sBaseUrl)
{
  AQCGI_SERVICE *sv;
  int rv;

  DBG_ERROR(NULL, "Creating aqhome-cgi environment in \"%s\"", sPathRuntimeFiles);
  sv=AQH_ServiceFiles_new(sPathRuntimeFiles, sBaseUrl);
  rv=AQH_ModAdmin_Create(sv);
  if (rv<0) {
    DBG_ERROR(NULL, "Error creating module \"admin\"");
    AQCGI_Service_free(sv);
    return rv;
  }

  rv=AQH_ModAdmModules_Create(sv);
  if (rv<0) {
    DBG_ERROR(NULL, "Error creating module \"modules\"");
    AQCGI_Service_free(sv);
    return rv;
  }

  rv=AQH_ModAdmUsers_Create(sv);
  if (rv<0) {
    DBG_ERROR(NULL, "Error creating module \"users\"");
    AQCGI_Service_free(sv);
    return rv;
  }

  rv=AQH_ModDevices_Create(sv);
  if (rv<0) {
    DBG_ERROR(NULL, "Error creating module \"devices\"");
    AQCGI_Service_free(sv);
    return rv;
  }

  AQCGI_Service_free(sv);
  return 0;
}




