#include <Foundation/NSObject.h>

#include "TestCase.h"

#import <Pantomime/Message.h>
#import <Pantomime/Constants.h>
#import <Pantomime/NSDataExtensions.h>


@interface test_Message : TestCase
@end

@implementation test_Message

-(void) test_headers
{
static const char *msg=
"From: =?iso-8859-1?q?namn_h=E4r?= <zot@bar.com>\n"
"To: zot@test.org (zott), list@test2.net\n"
"Date: Mon, 19 Feb 2002 12:37 UTC\n"
"Subject: =?utf-8?B?SGFs?=\n\t=?utf-8?b?bMOl?=\n"
"Mime-version: 1.0\n"
"\n"
"Subject: foo";

	NSData *dmsg=[NSData dataWithBytes: msg length: strlen(msg)];
	Message *m=[[Message alloc] init];

	InternetAddress *f;

	[m setHeadersFromData: dmsg];

	[self equalString: @"Hallå" : [m subject]];

	f=[m from];
	[self equalString: @"namn här" : [f personal]];
	[self equalString: @"zot@bar.com" : [f address]];

/* TODO: test all? */
/*- (NSString *) messageID;
- (NSCalendarDate *) receivedDate;
- (NSArray *) recipients;
- (InternetAddress*) replyTo;
- (Flags *) flags;
- (NSString *) mimeVersion;
- (id) headerValueForName: (NSString *) theName;
- (NSString *) organization;
- (NSCalendarDate *) resentDate;
- (InternetAddress *) resentFrom;
- (NSString *) resentMessageID;
- (NSString *) resentSubject;*/


	DESTROY(m);
}

-(void) test_basic_content
{
static const char *msg=
"From: =?iso-8859-1?q?namn_h=E4r?= <zot@bar.com>\n"
"To: zot@test.org (zott), list@test2.net\n"
"Date: Mon, 19 Feb 2002 12:37 UTC\n"
"Subject: =?utf-8?B?SGFs?=\n\t=?utf-8?b?bMOl?=\n"
"Mime-version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
"Content-Transfer-Encoding: 8bit\n"
"\n"
"hallå där!\n"
"\n";

	NSData *dmsg=[NSData dataWithBytes: msg length: strlen(msg)];
	Message *m=[[Message alloc] initWithData: dmsg];

	[self objectIsKindOf: [NSString class] : [m content]];
	[self equalString: @"hallå där!\n\n" : (NSString *)[m content]];

	DESTROY(m);
}

-(void) test_attachment
{
static const char *msg=
"From: Alexander Malmberg <alex@beta.malmberg.org>\n"
"Subject: test attach\n"
"Date: Mon, 01 Oct 2001 21:30:27 +0200\n"
"Lines: 34\n"
"Message-ID: <foo@beta.malmberg.org>\n"
"Mime-Version: 1.0\n"
"Content-Type: multipart/mixed; boundary=\"the_boundary\"\n"
"\n"
"This is ignored.\n"
"--the_boundary\n"
"Content-Type: text/plain; charset=us-ascii\n"
"Content-Transfer-Encoding: 7bit\n"
"\n"
"test\n"
"--the_boundary\n"
"Content-Type: text/plain; charset=us-ascii; name=\"hello.c\"\n"
"Content-Transfer-Encoding: base64\n"
"Content-Disposition: inline; filename=\"hello.c\"\n"
"\n"
"I2luY2x1ZGUgPHN0ZGlvLmg+CgppbnQgbWFpbihpbnQgYXJnYyxjaGFyICoq\n"
"YXJndikKewoJcHJpbnRmKCJIZWxsbywgd29ybGQhXG4iKTsKCXJldHVybiAw\n"
"Owp9Cg==\n"
"--the_boundary--\n"
"This is ignored too.\n";

	NSData *dmsg=[NSData dataWithBytes: msg length: strlen(msg)];
	Message *m=[[Message alloc] initWithData: dmsg];

	MimeMultipart *mp;
	Part *p1,*p2;

	mp=(MimeMultipart *)[m content];
	[self objectIsKindOf: [MimeMultipart class] : mp];

	[self equalInt: 2 : [mp count]  msg: @"part count"];
	p1=[mp bodyPartAtIndex: 0];
	p2=[mp bodyPartAtIndex: 1];
	[self objectIsKindOf: [MimeBodyPart class] : p1];
	[self objectIsKindOf: [MimeBodyPart class] : p2];

	[self objectIsKindOf: [NSString class] : [p1 content]];
	[self objectIsKindOf: [NSString class] : [p2 content]];

	[self equalString: @"test" : (NSString *)[p1 content]];

	[self equalString:
@"#include <stdio.h>\n"
@"\n"
@"int main(int argc,char **argv)\n"
@"{\n"
@"\tprintf(\"Hello, world!\\n\");\n"
@"\treturn 0;\n"
@"}\n" : (NSString *)[p2 content]];

	DESTROY(m);
}


-(void) test_unusual_encodings
{
static const char *msgs[]={
"Mime-version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"\n"
"Hebrew \xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d\n\n",

"Mime-version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: quoted-printable\n"
"\n"
"Hebrew =D7=A9=D7=9C=\n=D7=95=D7=9D\n\n", /* test soft-line-break-unfolding too */

"Mime-version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: base64\n"
"\n"
"SGVicmV3INep15zXldedCgo=\n",


"Mime-version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-8\n"
"Content-Transfer-Encoding: 8bit\n"
"\n"
"Hebrew \xf9\xec\xe5\xed\n\n",

"Mime-version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-8\n"
"Content-Transfer-Encoding: quoted-printable\n"
"\n"
"Hebrew =f9=ec=e5=ed\n\n",

"Mime-version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-8\n"
"Content-Transfer-Encoding: base64\n"
"\n"
"SGVicmV3IPns5e0KCg==\n",

};

/* Hebrew: */
static unichar correct[]={
0x0048,0x0065,0x0062,0x0072,0x0065,0x0077,0x0020,0x05e9,0x05dc,0x05d5,0x05dd,
0x000a,0x000a,
};

/*
Thai sample:

UTF-8:
"Thai	(à¸ à¸²à¸©à¸²à¹„à¸—à¸¢)	à¸ªà¸§à¸±à¸ªà¸”à¸µà¸„à¸£à¸±à¸š, à¸ªà¸§à¸±à¸ªà¸”à¸µà¸„à¹ˆà¸°\n"

ISO-8859-11: unsupported :(
"Thai	( 2)2D\")	*'1*5#1, *'1*5H0\\="

static unichar correct[]={
0x054,0x068,0x061,0x069,0x009,0x028,0xe20,0xe32,0xe29,0xe32,0xe44,0xe17,
0xe22,0x029,0x009,0xe2a,0xe27,0xe31,0xe2a,0xe14,0xe35,0xe04,0xe23,0xe31,
0xe1a,0x02c,0x020,0xe2a,0xe27,0xe31,0xe2a,0xe14,0xe35,0xe04,0xe48,0xe30,
0x00a,0x00a,0x00a
};
*/

	NSData *dmsg;
	Message *m;
	NSString *s;
	int i,l,ca;

	NSString *msg;

	for (ca=0;ca<sizeof(msgs)/sizeof(msgs[0]);ca++)
	{
		msg=[NSString stringWithFormat: @"case %i",ca];
	
		dmsg=[NSData dataWithBytes: msgs[ca] length: strlen(msgs[ca])];
		m=[[Message alloc] initWithData: dmsg];
		s=(NSString *)[m content];
		[self objectIsKindOf: [NSString class] : s];

		l=[s length];
		[self equalInt: sizeof(correct)/sizeof(correct[0]) : l  msg: msg];

		for (i=0;i<l;i++)
			[self equalUnichar: correct[i] : [s characterAtIndex: i]  msg: msg];
	}

#if 0
	{
		int i;
		NSString *s=[m content];
		unichar c;
		for (i=0;i<[s length];i++)
		{
			c=[s characterAtIndex: i];
/*			if (c>=0xe00)
				c=c-0xe00+0xa0;*/
			printf("%c",c);
/*			printf("0x%04x\n",c);*/
		}
	}
#endif

	DESTROY(m);
}


-(void) test_format_flowed
{
static const char *msg=
"Content-Type: text/plain; charset=iso-8859-1; format=flowed\n"
"Content-Transfer-Encoding: 8bit\n"
"\n"
"This is a long line \nthat should be combined \nto one line.\n"
"> This is a quoted line \n> that should be combined.\n"
"The end.\n";

	NSData *dmsg=[NSData dataWithBytes: msg length: strlen(msg)];
	Message *m=[[Message alloc] initWithData: dmsg];

	[self objectIsKindOf: [NSString class] : [m content]];
	[self equalString: @"This is a long line that should be combined to one line.\n> This is a quoted line that should be combined.\nThe end." : (NSString *)[m content]];

	DESTROY(m);
}



-(void) test_sending_data_multipart
{
static unsigned char part_2_2_content[]={
0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0,
0x00,0x01,0x0a,0x0d,0xff,0x00};

static NSString *part_1_content=
@"This is a plain text version of the message. It doesn't need any special\n"
@"handling. åäö ÅÄÖ.\n";

static NSString *part_2_1_content=
@"<html><head><title>test message</title></head>\n"
@"<body bgcolor=\"blue\" text=\"red\">\n"
@"This is a test_message in <b>html</b>. It has long lines and funny "
@"characters (like åäö) and <font color=\"black\">attributes</font>.<p>"
@"Lots of quoting necessary! It can reference the image in the other part "
@"of this message using the Content-ID.\n";

static unichar subject[]={0x05e9,0x05dc,0x05d5,0x05dd};
//static unichar subject[]={0x41,0x42,0x43};

/* TODO: this causes it to fall back on utf-8, so it encodes everything
correctly, but it might be better to split it into words and use
different iso-8859-* charsets for different parts, eg.:

Many enc =?iso-8859-8?q?foo?= =?iso-8859-1?q?bar?=
*/
static unichar part_2_2_description[]={'M','a','n','y',' ','e','n','c',' ',0x05e9,0x05dc,0x05d5,0x05dd,' ','å','ä','ö','!'};

static NSString *from_personal=@"nåt som behöver kodas";
static NSString *from_address=@"foo@bar.com";

	Message *b;
	MimeMultipart *mp,*mp2;
	MimeBodyPart *p1,*p2,*p3;

	NSString *s_subject;
	NSString *s_part_2_2_description;
	NSData *d_part_2_2_content;

	NSData *got;


	s_subject=[NSString stringWithCharacters: subject length: sizeof(subject)/sizeof(subject[0])];
	s_part_2_2_description=[NSString stringWithCharacters: part_2_2_description
			length: sizeof(part_2_2_description)/sizeof(part_2_2_description[0])];
	d_part_2_2_content=[NSData dataWithBytes: part_2_2_content  length: sizeof(part_2_2_content)];

	b=[[Message alloc] init];
	[b setContentType: @"multipart/alternative"];
	[b setContentTransferEncoding: EIGHTBIT];

	[b setFrom: [[InternetAddress alloc]
		initWithPersonal: from_personal andAddress: from_address]];
	[b setSubject: s_subject];

	mp=[[MimeMultipart alloc] init];
	[b setContent: (NSObject *)mp];

	p1=[[MimeBodyPart alloc] init];
	[mp addBodyPart: p1];
	[p1 setContentType: @"text/plain"];
	[p1 setCharset: @"iso-8859-1"];
	[p1 setContentTransferEncoding: EIGHTBIT];
	[p1 setContent: part_1_content];

	p1=[[MimeBodyPart alloc] init];
	[mp addBodyPart: p1];
	[p1 setContentType: @"multipart/mixed"];
	mp2=[[MimeMultipart alloc] init];
	[p1 setContent: mp2];

	p2=[[MimeBodyPart alloc] init];
	[p2 setContentType: @"text/html"];
	[p2 setContentTransferEncoding: QUOTEDPRINTABLE];
	[p2 setCharset: @"iso-8859-1"];
	[p2 setContent: part_2_1_content];

	[mp2 addBodyPart: p2];

	p3=[[MimeBodyPart alloc] init];
	[p3 setFilename: @"foo.image"];
	[p3 setContentType: @"image/x-someformat"];
	[p3 setContentTransferEncoding: BASE64];
	[p3 setContentID: @"_image-content-id_"];
	[p3 setContent: d_part_2_2_content];
	[p3 setContentDescription: s_part_2_2_description];

	[mp2 addBodyPart: p3];


//	printf("done creating\n");
	got=[b dataUsingSendingMode: SEND_TO_FOLDER];
//	printf("got data\n");
//	printf("got\n||\n%s\n||\n",[got cString]);
	{ /* now lets make sure it parsed to what we sent */
		Message *m2=[[Message alloc] initWithData: got];
		MimeMultipart *mp1,*mp2;
		MimeBodyPart *p1,*p2,*p21,*p22;
//		printf("init new message\n");

		[self equalString: s_subject : [m2 subject]];
		[self equalString: from_personal : [[m2 from] personal]];
		[self equalString: from_address : [[m2 from] address]];
		[self equalString: @"multipart/alternative" : [m2 contentType]];

		[self objectIsKindOf: [MimeMultipart class] : [m2 content]];
		mp1=(MimeMultipart *)[m2 content];
		[self equalInt: 2 : [mp1 count]  msg: @"correct count for mp1"];

		p1=[mp1 bodyPartAtIndex: 0];
		[self equalString: @"text/plain" : [p1 contentType]];
		[self objectIsKindOf: [NSString class] : [p1 content]];
		[self equalString: part_1_content : (NSString *)[p1 content]];

		p2=[mp1 bodyPartAtIndex: 1];
		[self equalString: @"multipart/mixed" : [p2 contentType]];
		[self objectIsKindOf: [MimeMultipart class] : [p2 content]];
		mp2=(MimeMultipart *)[p2 content];
		p21=[mp2 bodyPartAtIndex: 0];
		p22=[mp2 bodyPartAtIndex: 1];

		[self equalString: @"text/html" : [p21 contentType]];
		[self objectIsKindOf: [NSString class] : [p21 content]];
		[self equalString: part_2_1_content : (NSString *)[p21 content]];

		[self objectIsKindOf: [NSData class] : [p22 content]];
		[self equalData: d_part_2_2_content : (NSData *)[p22 content]];

		DESTROY(m2);
	}
//	printf("  done\n");
}

@end

