/** BEGIN COPYRIGHT BLOCK
 * Copyright (C) 2001 Sun Microsystems, Inc.  Used by permission.
 * Copyright (C) 2005 Red Hat, Inc.
 * All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation version
 * 2.1 of the License.
 *                                                                                  
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *                                                                                  
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * END COPYRIGHT BLOCK **/
/*
 * error.c - Handle error recovery
 *
 * All blame to Mike McCool
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <nspr.h>
#include <libadminutil/admutil.h>

#ifdef XP_WIN32
#include <windows.h>
#endif

#include "dbtadmutil.h"
extern Resource *admutil_i18nResource;
extern char *admutil_acceptLang;

PR_IMPLEMENT(char *)
alert_wrd_wrap(char *str, int width, char *linefeed)
{
    char *ans = NULL;
    int counter=0;
    int lsc=0, lsa=0;
    register int strc=0, ansc=0;
    register int x=0;
 
    /* assume worst case */
    ans = (char *) PR_Malloc((PL_strlen(str)*PL_strlen(linefeed))+32);
 
    for(strc=0, ansc=0; str[strc]; /*none*/)  {
        if(str[strc]=='\n')  {
            counter=0;
            lsc=0, lsa=0;
            for(x=0; linefeed[x]; x++)  {
                ans[ansc++]=linefeed[x];
             }
            strc++;
        }  else if(str[strc]=='\r')  {
            strc++;
        }  else if(str[strc]=='\\')  {
            ans[ansc++]='\\';
            ans[ansc++]=strc++;
        }  else  {
            if(counter==width)  {
                if(lsc && lsa)  {
                    strc=lsc;
                    ansc=lsa;
 
                    counter=0;
                    lsc=0, lsa=0;
                    for(x=0; linefeed[x]; x++)  {
                        ans[ansc++]=linefeed[x];
                    }
                    strc++;
                }  else  {
                /* else, you're a loser, I'm breaking your big word anyway */
                    counter=0;
                    lsc=0, lsa=0;
                    for(x=0; linefeed[x]; x++)  {
                        ans[ansc++]=linefeed[x];
                    }
                    strc++;
                }
            }  else  {
                if(str[strc] == ' ')  {
                    lsc=strc;
                    lsa=ansc;
                }
                ans[ansc++]=str[strc++];
                counter++;
            }
        }
    }
    ans[ansc]='\0';
    return ans;
}
 


/* Be sure to edit libadminutil/admutil.h and add new #define types for these headers. */
char *err_headers[NMC_MAX_ERROR] =
  {"File System Error",
   "Memory Error",
   "System Error",
   "Incorrect Usage",
   "Form Element Missing",
   "Registry Database Error",
   "Network Error",
   "Unexpected Failure",
   "Application Error",
   "Warning"};



#ifdef XP_UNIX
#define get_err() errno
#define verbose_err() system_errmsg()
#else /* XP_WIN32 */
int get_err()
{
  /* Convert to use NSPR  */
  return PR_GetOSError();
}
char *verbose_err()
{
  /* Convert to use NSPR  */
  char *retval = NULL;
  char *errMsg = NULL;
  PRInt32 errMsgLen = 0;

  errMsgLen = PR_GetErrorTextLength();
  if (errMsgLen > 0) {
      errMsg = PR_Malloc(errMsgLen+1);
      if (errMsg) {
          errMsgLen = PR_GetErrorText(errMsg);
          if (errMsgLen) {
              retval = alert_wrd_wrap(errMsg, WORD_WRAP_WIDTH, "\\n");
          }
          PR_Free(errMsg);
      }
  }
  return retval;
}
#endif /* XP_WIN32 */

void _rpt_err(int type, const char *info, const char *details, const char* extra, int shouldexit)
{
  const char *errorString = NULL;
  char* acceptLang = admutil_acceptLang;
  int needfree = 0;

  if (admutil_i18nResource) {
    needfree = 1;
    switch (type) {
    case FILE_ERROR:
      errorString = res_getstring(admutil_i18nResource, DBT_errRpt_FILE_ERROR, acceptLang, NULL, 0, NULL);
      break;
    case MEMORY_ERROR:
      errorString = res_getstring(admutil_i18nResource, DBT_errRpt_MEMORY_ERROR, acceptLang, NULL, 0, NULL);
      break;
    case SYSTEM_ERROR:
      errorString = res_getstring(admutil_i18nResource, DBT_errRpt_SYSTEM_ERROR, acceptLang, NULL, 0, NULL);
      break;
    case INCORRECT_USAGE:
      errorString = res_getstring(admutil_i18nResource, DBT_errRpt_INCORRECT_USAGE, acceptLang, NULL, 0, NULL);
      break;
    case ELEM_MISSING:
      errorString = res_getstring(admutil_i18nResource, DBT_errRpt_ELEM_MISSING, acceptLang, NULL, 0, NULL);
      break;
    case REGISTRY_DATABASE_ERROR:
      errorString = res_getstring(admutil_i18nResource, DBT_errRpt_REGISTRY_DATABASE_ERROR, acceptLang, NULL, 0, NULL);
      break;
    case NETWORK_ERROR:
      errorString = res_getstring(admutil_i18nResource, DBT_errRpt_NETWORK_ERROR, acceptLang, NULL, 0, NULL);
      break;
    case GENERAL_FAILURE:
      errorString = res_getstring(admutil_i18nResource, DBT_errRpt_GENERAL_FAILURE, acceptLang, NULL, 0, NULL);
      break;
    case WARNING:
      errorString = res_getstring(admutil_i18nResource, DBT_errRpt_WARNING, acceptLang, NULL, 0, NULL);
      break;
    case APP_ERROR:
      errorString = res_getstring(admutil_i18nResource, DBT_errRpt_APP_ERROR, acceptLang, NULL, 0, NULL);
      break;
    default:
      errorString = NULL;
      needfree = 0;
    }
  }
  else errorString =  err_headers[type];

  /* Be sure headers are terminated. */
  fprintf(stdout, "Content-type: text/html\n\n");
  if (shouldexit) fprintf(stdout, "NMC_Status: 1\n");
  else fprintf(stdout, "NMC_Status: 2\n");
  if (type >= 0 && type < NMC_MAX_ERROR)
    fprintf(stdout, "NMC_ErrType: %s\n", errorString);
  else fprintf(stdout, "NMC_ErrType: Unknown Error Type (%d)\n", type);
  if (info) fprintf(stdout, "NMC_ErrInfo: %s\n", info);
  if (details) fprintf(stdout, "NMC_ErrDetail: %s\n", details);
  if (extra) fprintf(stdout, "%s\n", extra);

  if (needfree) {
    PL_strfree((char *)errorString);
  }

  if(shouldexit)  {
#ifdef  XP_WIN32
    WSACleanup();
#endif
    exit(0);
  }
}


PR_IMPLEMENT(void)
rpt_err(int type, const char *info, const char *details, const char *extra)
{
    _rpt_err(type, info, details, extra, 1);
}

PR_IMPLEMENT(void)
rpt_warning(int type, const char *info, const char *details, const char *extra)
{
    _rpt_err(type, info, details, extra, 0);
}

PR_IMPLEMENT(void)
rpt_unknown(const char *description)
{
    fprintf(stdout, "Content-type: text/html\n\n");
    fprintf(stdout, "NMC_Status: 3\n");
    if (description) fprintf(stdout, "NMC_Description: %s\n", description);
}


PR_IMPLEMENT(void)
rpt_success(const char *description)
{
    /* Be sure headers are terminated. */
    fprintf(stdout, "Content-type: text/html\n\n");
    fprintf(stdout, "NMC_Status: 0\n");
    if (description) fprintf(stdout, "NMC_Description: %s\n", description);

}
