/*
 * Copyright (C) 2007 JasperSoft http://www.jaspersoft.com
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed WITHOUT ANY WARRANTY; and without the 
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see http://www.gnu.org/licenses/gpl.txt 
 * or write to:
 * 
 * Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330,
 * Boston, MA  USA  02111-1307
 */

#include <stdio.h>
#include "services.h"
#include "marshaller.h"
#include "unmarshaller.h"
 
#include "soap/soapH.h"
#include "soap/repositorySoapBinding.nsmap"

void jasperserver_store_soap_error(jasperserver_operation_result_t *response, struct soap *soap);

void jasperserver_init_soap(jasperserver_server_t *server, struct soap *soap)
{
     soap_init(soap);
     soap->userid = (char *)JS_CSTR(server->username);
     soap->passwd = (char *)JS_CSTR(server->password);
     soap->encodingStyle = "http://xml.apache.org/xml-soap/literalxml";
}

void jasperserver_end_soap(struct soap *soap)
{
     soap_destroy(soap);
     soap_end(soap);
     soap_done(soap);
}


jasperserver_string_t *jasperserver_get_file_parent(char* path)
{
     char* str = NULL;
     str = path;
     jasperserver_string_t *newPath = NULL;
     newPath = jasperserver_string_new();
     
     
     // Set the correct path separator..
     while (strchr(str,'\\') )
     {
           str = strchr(str,'\\');
           *str = '/'; 
     }
     
     str = path;
     while (strchr(str,'/'))
     {
           str = strchr(str,'/');
           str++; 
     }
     
     if (str != path)
     {
        int len = 0;
        str--;
        len = str - path;
        
        xmlBufferAdd(newPath->buffer , path, len);
     }
     
     return newPath;
}

jasperserver_operation_result_t * jasperserver_ws_list(jasperserver_server_t *server, jasperserver_request_t *request)
{
  struct soap soap;
  int rc = 0;
  jasperserver_string_t *request_xml = NULL;
  jasperserver_string_t *response_xml = NULL;
  jasperserver_operation_result_t *operationResult = NULL;
  char* response_buffer = NULL;
  
  request_xml = jasperserver_string_new();
  rc = jasperserver_request_marshal(request, request_xml);
  if (rc < 0) {
        printf("jasperserver_ws_list: Error at jasperserver_request_marshal\n");
        return NULL;
  }
  
  jasperserver_init_soap(server, &soap);
  
  soap_call_ns1__list(&soap, JS_CSTR(server->url), "", (char *)JS_CSTR(request_xml), &response_buffer);
  
  jasperserver_string_free(request_xml);
  
  if (soap.error)
  { 
    operationResult = jasperserver_operation_result_new();
    operationResult->returnCode = -1;
    jasperserver_store_soap_error(operationResult, &soap);
  }
  else
  {
    //printf("Result %s\n", response_xml);
    //fflush(stdout);
    response_xml = jasperserver_string_new();
    jasperserver_string_cappend(response_xml, BAD_CAST response_buffer );
    operationResult = jasperserver_response_unmarshal(response_xml);
  }
  
  jasperserver_end_soap( &soap );
  
  return operationResult;
}
 
jasperserver_operation_result_t * jasperserver_ws_delete(jasperserver_server_t *server, jasperserver_request_t *request)
{
  struct soap soap;
  int rc = 0;
  jasperserver_string_t *request_xml = NULL;
  jasperserver_string_t *response_xml = NULL;
  jasperserver_operation_result_t *operationResult = NULL;
  char* response_buffer = NULL;
  
  request_xml = jasperserver_string_new();
  rc = jasperserver_request_marshal(request, request_xml);
  if (rc < 0) {
        printf("jasperserver_ws_delete: Error at jasperserver_request_marshal\n");
        return NULL;
  }
  
  jasperserver_init_soap(server, &soap);
  
  soap_call_ns1__delete(&soap, JS_CSTR(server->url), "", (char *)JS_CSTR(request_xml), &response_buffer);
  
  if (soap.error)
  { 
    operationResult = jasperserver_operation_result_new();
    operationResult->returnCode = -1;
    jasperserver_store_soap_error(operationResult, &soap);
  }
  else
  {
    //printf("Result %s\n", response_xml);
    //fflush(stdout);
    response_xml = jasperserver_string_new();
    jasperserver_string_cappend(response_xml, BAD_CAST response_buffer );
    operationResult = jasperserver_response_unmarshal(response_xml);
  }
  
  jasperserver_string_free(request_xml);
  
  jasperserver_end_soap( &soap );
 
  return operationResult;
}
 
jasperserver_operation_result_t * jasperserver_ws_get(jasperserver_server_t *server, jasperserver_request_t *request, char *filename)
{
  struct soap soap;
  int rc = 0;
  struct soap_multipart *attachment;
  jasperserver_string_t *request_xml = NULL;
  jasperserver_string_t *response_xml = NULL;
  jasperserver_operation_result_t *operationResult = NULL;
  char* response_buffer = NULL;
  
  request_xml = jasperserver_string_new();
  rc = jasperserver_request_marshal(request, request_xml);
  if (rc < 0) {
        printf("jasperserver_ws_get: Error at jasperserver_request_marshal\n");
        return NULL;
  }
  
  jasperserver_init_soap(server, &soap);
  
  soap_call_ns1__get(&soap, JS_CSTR(server->url), "", (char *)JS_CSTR(request_xml), &response_buffer);
  
  if (soap.error)
  { 
    operationResult = jasperserver_operation_result_new();
    operationResult->returnCode = -1;
    jasperserver_store_soap_error(operationResult, &soap);
  }
  else
  {
    //printf("Result %s\n", response_xml);
    //fflush(stdout);
    response_xml = jasperserver_string_new();
    jasperserver_string_cappend(response_xml, BAD_CAST response_buffer );
    operationResult = jasperserver_response_unmarshal(response_xml);
    
    if (filename)
    {
        for (attachment = soap.mime.list; attachment; attachment = attachment->next)
        {
          if ((*attachment).id && !strncmp((*attachment).id,"<attachment>", strlen("<attachment>")))
          {
          	FILE *fp=fopen( filename,"wb");
          	if (fp) 
            {
                fwrite((*attachment).ptr, (*attachment).size,1, fp);
          	    fclose(fp);
            }
            else
            {
                fprintf(stderr, "Unable to open file: %s\n", filename);
                fflush(stderr);
            }
            break;
          }
        }
    }
  }
  
  jasperserver_end_soap( &soap );
  jasperserver_string_free(request_xml);
 
  return operationResult;
}

jasperserver_operation_result_t * jasperserver_ws_runReport(jasperserver_server_t *server, jasperserver_request_t *request, char *filename)
{
  struct soap soap;
  int rc = 0;
  struct soap_multipart *attachment;
  jasperserver_string_t *request_xml = NULL;
  jasperserver_string_t *response_xml = NULL;
  jasperserver_operation_result_t *operationResult = NULL;
  char* response_buffer = NULL;
  
  request_xml = jasperserver_string_new();
  rc = jasperserver_request_marshal(request, request_xml);
  if (rc < 0) {
        printf("jasperserver_ws_runReport: Error at jasperserver_request_marshal\n");
        return NULL;
  }
  
  jasperserver_init_soap(server, &soap);
  
  soap_call_ns1__runReport(&soap, JS_CSTR(server->url), "", (char *)JS_CSTR(request_xml), &response_buffer);
  
  if (soap.error)
  { 
    operationResult = jasperserver_operation_result_new();
    operationResult->returnCode = -1;
    jasperserver_store_soap_error(operationResult, &soap);
  }
  else
  {
    int attachNum = 0;
    //printf("Result %s\n", response_xml);
    //fflush(stdout);
    response_xml = jasperserver_string_new();
    jasperserver_string_cappend(response_xml, BAD_CAST response_buffer );
    operationResult = jasperserver_response_unmarshal(response_xml);
    
    if (filename)
    {
        jasperserver_string_t *dir = NULL;
        dir = jasperserver_get_file_parent(filename);
        if (JS_NOTNULL(dir))
        {
           jasperserver_string_cappend(dir,"/images");
        }
        else
        {
            jasperserver_string_cappend(dir,"images");
        }
        
        for (attachment = soap.mime.list; attachment; attachment = attachment->next)
        {
          attachNum++;
          if ((*attachment).id && !strncmp((*attachment).id,"<report>", strlen("<report>")))
          {
          	FILE *fp=fopen( filename,"wb");
          	if (fp) 
            {
                fwrite((*attachment).ptr, (*attachment).size,1, fp);
          	    fclose(fp);
            }
            else
            {
                fprintf(stderr, "Unable to open file: %s\n", filename);
                fflush(stderr);
            }
            break;
          }
          else if ((*attachment).id && !strncmp((*attachment).id,"<img_", strlen("<img_")))
          {
               int img_name_len = 0;
               char *image_name_str = NULL;
               
               mkdir(JS_CSTR(dir),0755);
               
               img_name_len = strlen((*attachment).id) + strlen(JS_CSTR(dir)) + 2;
               image_name_str = (char *)malloc(img_name_len);
               sprintf(image_name_str,"%s/",JS_CSTR(dir));
               strncat(image_name_str, (char *)((attachment->id)+1), strlen((*attachment).id)-2); 
               
               FILE *fp=fopen( image_name_str,"wb");
         	   if (fp) 
               {
                    fwrite((*attachment).ptr, (*attachment).size,1, fp);
              	    fclose(fp);
               }
               else
               {
                    fprintf(stderr, "Unable to open file: %s\n", image_name_str);
                    fflush(stderr);
               }
               
               free(image_name_str);
               
          }
        }
        
        jasperserver_string_free(dir);
    }
  }
  
  jasperserver_end_soap( &soap );
  jasperserver_string_free(request_xml);
  
  return operationResult;
}
 
jasperserver_operation_result_t * jasperserver_ws_put(jasperserver_server_t *server, jasperserver_request_t *request, char *filename)
{
  struct soap soap;
  int rc = 0;
  struct soap_multipart *attachment;
  jasperserver_string_t *request_xml = NULL;
  jasperserver_string_t *response_xml = NULL;
  jasperserver_operation_result_t *operationResult = NULL;
  char* response_buffer = NULL;
  
  request_xml = jasperserver_string_new();
  rc = jasperserver_request_marshal(request, request_xml);
  if (rc < 0) {
        printf("jasperserver_ws_runReport: Error at jasperserver_request_marshal\n");
        return NULL;
  }
  
  jasperserver_init_soap(server, &soap);
  if (filename != NULL)
  {
      soap_set_dime(&soap);
      rc = jasperserver_attach_file(&soap, filename);
      if (rc != 0)
      {
         operationResult = jasperserver_operation_result_new();
         operationResult->returnCode = -1;
         jasperserver_string_format(operationResult->returnMessage, "Unable to attach file %s: error [%d]",filename, rc);
      }
  }
  
  soap_call_ns1__put(&soap, JS_CSTR(server->url), "", (char *)JS_CSTR(request_xml), &response_buffer);
  
  if (soap.error)
  { 
    operationResult = jasperserver_operation_result_new();
    operationResult->returnCode = -1;
    jasperserver_store_soap_error(operationResult, &soap);
  }
  else
  {
    //printf("Result %s\n", response_xml);
    //fflush(stdout);
    response_xml = jasperserver_string_new();
    jasperserver_string_cappend(response_xml, BAD_CAST response_buffer );
    operationResult = jasperserver_response_unmarshal(response_xml);
  }
  
  jasperserver_end_soap( &soap );
  jasperserver_string_free(request_xml);
 
  return operationResult;
}


/*
*
*
*/
void jasperserver_store_soap_error(jasperserver_operation_result_t *response, struct soap *soap)
{
   int written = 0;
   if (soap_check_state(soap))
    jasperserver_string_cset(response->returnMessage, "Error: soap struct not initialized\n");
  else if (soap->error)
  { const char *c, *v = NULL, *s, **d;
    d = soap_faultcode(soap);
    if (!*d)
      soap_set_fault(soap);
    c = *d;
    if (soap->version == 2)
      v = *soap_faultsubcode(soap);
    s = *soap_faultstring(soap);
    d = soap_faultdetail(soap);
    
    jasperserver_string_format(response->returnMessage, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]");
     
  }
}
