/*
  Copyright (C) 2000-2004 SKYRIX Software AG

  This file is part of OpenGroupware.org.

  OGo 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; either version 2, or (at your option) any
  later version.

  OGo 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 OGo; see the file COPYING.  If not, write to the
  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  02111-1307, USA.
*/

#include "NGMimeMessageGenerator.h"
#include "NGMimeMessage.h"
#include <NGMime/NGMimeFileData.h>
#include "common.h"

/* Defaults
  Mail_Use_8bit_Encoding_For_Text[BOOL] --
    Use 8bit content-transfer-encoding for
    text messages
*/

NSData *
_base64Encoding(NGMimeBodyGenerator *self,
                NSData *_data_,
                id<NGMimePart>_part,
                NGMutableHashMap *_addHeaders)
{
  NSString   *transEnc = nil;  
  const char *bytes    = NULL;
  unsigned   length    = 0;

  if ([_data_ isKindOfClass:[NGMimeFileData class]])
    return _data_;
  
  bytes  = [_data_ bytes];
  length = [_data_ length];

  while (length > 0) {
    if ((unsigned char)*bytes > 127) {
      break;
    }
    bytes++;
    length--;
  }
  if (length > 0) { // should be encoded
    NGMimeType *type;

    type = [_part contentType];
    
    if ([[type type] isEqualToString:@"text"] == YES) {
      NSUserDefaults *ud;
      BOOL use8bit;

      ud      = [NSUserDefaults standardUserDefaults];
      use8bit = [ud boolForKey:@"Mail_Use_8bit_Encoding_For_Text"];
      
      if (use8bit)
        transEnc = @"8bit";
      else {
        _data_   = [_data_ dataByEncodingQuotedPrintable];
        transEnc = @"quoted-printable";
      }
    }
    else {
      NGMimeType *appOctet;
      
      _data_   = [_data_ dataByEncodingBase64];
      transEnc = @"base64";

      appOctet = [NGMimeType mimeType:@"application" subType:@"octet-stream"];
      if (type == nil)
        [_addHeaders setObject:appOctet forKey:@"content-type"];
    }
  }
  else /* no encoding */
    transEnc = @"7bit";
  
  [_addHeaders setObject:transEnc forKey:@"content-transfer-encoding"];
  [_addHeaders setObject:[NSNumber numberWithInt:[_data_ length]]
                      forKey:@"content-length"];
  return _data_;
}

@implementation NGMimeMessageGenerator

+ (int)version {
  return 2;
}
+ (void)initialize {
  NSAssert2([super version] == 2,
            @"invalid superclass (%@) version %i !",
            NSStringFromClass([self superclass]), [super version]);
}

/* header field specifics */

- (NSData *)generateDataForHeaderField:(NSString *)_headerField
  value:(id)_value
{
  NSData *data = nil;

  data = [super generateDataForHeaderField:_headerField
                value:_value];
  {
    const char   *bytes  = NULL;
    unsigned int length  = 0;
    unsigned int desLen  = 0;
    char         *des    = NULL;
    unsigned int cnt     = 0;
    BOOL         doEnc   = NO;
    NSString     *str;

#if APPLE_Foundation_LIBRARY || NeXT_Foundation_LIBRARY
    str = [[NSString alloc] initWithData:data
                            encoding:NSISOLatin1StringEncoding];
#else
    str = [[NSString alloc] initWithData:data
                            encoding:NSISOLatin9StringEncoding];
#endif
    str = [str autorelease];
    
    bytes  = [str cString];
    length = [str cStringLength];

    while (cnt < length) {
      if ((unsigned char)bytes[cnt] > 127) {
        doEnc = YES;
        break;
      }
      cnt++;
    }
    if (doEnc) {
      char        iso[]     = "=?iso-8859-15?q?";
      unsigned    isoLen    = 16;
      char        isoEnd[]  = "?=";
      unsigned    isoEndLen = 2;
      
      desLen = length * 3 + 20;
      
      des = calloc(desLen + 2, sizeof(char));
      
      // memcpy(des, bytes, cnt);
      memcpy(des, iso, isoLen);
      desLen = NGEncodeQuotedPrintableMime(bytes, length,
                                           des + isoLen, desLen - isoLen);
      if ((int)desLen != -1) {
        memcpy(des + isoLen + desLen, isoEnd, isoEndLen);
        
        data = [NSData dataWithBytesNoCopy:des
		       length:(isoLen + desLen + isoEndLen)];
      }
      else {
        NSLog(@"WARNING: An error occour during quoted-printable decoding");
        if (des != NULL) free(des);
      }
    }
  }
  return data;
}


/* content-transfer-encoding */

- (id<NGMimeBodyGenerator>)defaultBodyGenerator {
  NGMimeMessageBodyGenerator *gen;
  
  gen  = [[NGMimeMessageBodyGenerator alloc] init];
  [gen setUseMimeData:self->useMimeData];
  return gen;
}

- (id<NGMimeBodyGenerator>)generatorForBodyOfPart:(id<NGMimePart>)_part {
  id<NGMimeBodyGenerator> bodyGen;
  NGMimeType              *contentType;
  NSString                *type;
  Class generatorClass;
  
  if (self->delegateRespondsTo.generatorGeneratorForBodyOfPart) {
    bodyGen = [self->delegate mimePartGenerator:self
                              generatorForBodyOfPart:self->part];
  
    if (bodyGen != nil)
      return bodyGen;
  }
  
  if ((contentType = [_part contentType]) == nil)
    contentType = [self defaultContentTypeForPart:_part];
  
  if (contentType == nil) {
    NSLog(@"WARNING(%s): missing content-type in part 0x%08X.", _part);
    return nil;
  }
  
  type = [contentType type];

  generatorClass = Nil;
  if ([type isEqualToString:NGMimeTypeMultipart])
    generatorClass = [NGMimeMessageMultipartBodyGenerator class];
  else if ([type isEqualToString:NGMimeTypeText])
    generatorClass = [NGMimeMessageTextBodyGenerator class];
  else if (([type isEqualToString:NGMimeTypeMessage]) &&
           [[contentType subType] isEqualToString:@"rfc822"]) {
    generatorClass = [NGMimeMessageRfc822BodyGenerator class];
  }
  
  bodyGen = [[[generatorClass alloc] init] autorelease];
  [(id)bodyGen setUseMimeData:self->useMimeData];
  return bodyGen;
}

@end /* NGMimeMessageGenerator */
