/*
  Copyright (C) 2004-2005 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.
*/

#import <NGExtensions/NSNull+misc.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGMail/NGMimeMessageParser.h>

#import "UIxMailFormatter.h"

@implementation UIxSubjectFormatter

static Class StrClass  = Nil;
static Class DataClass = Nil;

+ (void)initialize {
  StrClass  = [NSString class];
  DataClass = [NSData   class];
}

- (id)init {
  if ((self = [super init])) {
    self->maxLength = 64;
  }
  return self;
}

/* configuration */

- (unsigned int)maxLength {
  return self->maxLength;
}

- (BOOL)shouldDecodeQP {
  return YES;
}

/* labels */

- (NSString *)missingSubjectLabel {
  return [self labelForKey:@"no_subject"];
}

/* specific formatters */

- (NSString *)stringForStringValue:(NSString *)_subject {
  NSString *s;
  
  /* quoted printable */
  if ([self shouldDecodeQP] && [_subject hasPrefix:@"=?"]) {
    /* 
       Now this is interesting. An NSString should not contain QP markers since
       it is already 'charset decoded'. This is also why the NGMime parser
       expects an NSData.
       
       Sample:
         =?iso-8859-1?q?Yannick=20DAmboise?=

       Note: -stringByDecodingQuotedPrintable only expands =D0 like charcodes!
    */
    NSData *data;
    
    /* header field data should always be ASCII */
    data = [_subject dataUsingEncoding:NSUTF8StringEncoding];
    return [self stringForDataValue:data];
  }
  
  if ([_subject length] == 0)
    return [self missingSubjectLabel];
  
  if ([_subject length] <= [self maxLength])
    return _subject;
  
  s = [_subject substringToIndex:([self maxLength] - 3)];
  return [s stringByAppendingString:@"..."];
}

- (NSString *)stringForDataValue:(NSData *)_subject {
  NSString *s, *r;
  unsigned len;
  
  if ((len = [_subject length]) == 0)
    return [self missingSubjectLabel];
  
  /* check for quoted printable */
  
  if (len > 6 && [self shouldDecodeQP]) {
    const unsigned char *b;
    
    b = [_subject bytes];
    if (b[0] == '=' && b[1] == '?') {
      /* eg: '=?iso-8859-1?q?Yannick=20DAmboise?=' */
      id t;
      
      t = [_subject decodeQuotedPrintableValueOfMIMEHeaderField:@"subject"];
      if ([t isNotNull])
	return [self stringForObjectValue:t];
      else
	[self warnWithFormat:@"decoding QP failed: '%@'", t];
    }
  }
  
  /* continue NSData processing */
  
  [self warnWithFormat:@"NSData subject, using UTF-8 to decode."];
  
  // TODO: exception handler?
  s = [[NSString alloc] initWithData:_subject encoding:NSUTF8StringEncoding];
  if (s == nil) {
    [self errorWithFormat:@"could do not decode NSData subject!"];
    return [self labelForKey:@"Error_CouldNotDecodeSubject"];
  }
  
  if ([s hasPrefix:@"=?"]) { // TODO: this should never happen?
    [self warnWithFormat:@"subject still has QP signature: '%@'", s];
    r = [s copy];
  }
  else
    r = [[self stringForStringValue:s] copy];
  [s release];
  return [r autorelease];
}

/* formatter entry function */

- (NSString *)stringForObjectValue:(id)_subject {
  if (![_subject isNotNull])
    return [self missingSubjectLabel];
  
  if ([_subject isKindOfClass:StrClass])
    return [self stringForStringValue:_subject];
  if ([_subject isKindOfClass:DataClass])
    return [self stringForDataValue:_subject];
  
  return [self stringForStringValue:[_subject stringValue]];
}

@end /* UIxSubjectFormatter */
