/*
copyright 2002 Alexander Malmberg <alexander@malmberg.org>
*/

#include <Foundation/NSObject.h>
#include <Foundation/NSString.h>
#include <Foundation/NSBundle.h>
#include <AppKit/NSWindowController.h>
#include <AppKit/NSWindow.h>
#include <AppKit/NSTextView.h>
#include <AppKit/NSScrollView.h>
#include <AppKit/NSClipView.h>
#include <AppKit/NSTextContainer.h>
#include <AppKit/NSTextField.h>
#include <AppKit/NSButton.h>
#include <GNUstepGUI/GSVbox.h>
#include <GNUstepGUI/GSHbox.h>

#include "ComposeWindowController.h"

#include "main.h"
#include "KeyWindow.h"
#include "Pref_Posting.h"

#include <Pantomime/Constants.h>
#include <Pantomime/Message.h>
#include <Pantomime/MimeUtility.h>
#include <Pantomime/InternetAddress.h>


@implementation ComposeWindowController


-(void) post: (id)sender
{
	Message *m=[[Message alloc] init];
	NSMutableDictionary *md;
	NSEnumerator *e;
	NSString *header,*value;
	NSData *d;

	if (state)
	{
		NSBeep();
		return;
	}

	if (![[tf_subject stringValue] length] ||
	    ![[tf_newsgroups stringValue] length] ||
	    ![[tf_from stringValue] length])
	{
		NSBeep();
		return;
	}

	md=[msg_headers mutableCopy];
	[md setObject: [tf_subject stringValue] forKey: @"Subject"];
	[md setObject: [tf_newsgroups stringValue] forKey: @"Newsgroups"];
	[md setObject: [tf_from stringValue] forKey: @"From"];

	for (e=[md keyEnumerator];(header=[e nextObject]);)
	{
		value=[md objectForKey: header];

		if ([header isEqualToString: @"From"])
		{
			InternetAddress *ia=[[InternetAddress alloc] initWithString: value];
			[m setFrom: ia];
			DESTROY(ia);
		}
		else if ([header isEqualToString: @"Subject"])
		{
			[m setSubject: value];
		}
		else
			[m addHeader: header  withValue: value];
	}

	[m setContentType: @"text/plain"];
	[m setContentTransferEncoding: PantomimeEncoding8bit];
	[m setFormat: PantomimeFormatFlowed];
	[m setContent: [text string]];

	[m setCharset: [MimeUtility charsetForString: [text string]]];

	state=1;
	d=[m dataValue];
	{
		NSData *nd=[[[@"Newsgroups: " stringByAppendingString: [md objectForKey: @"Newsgroups"]] stringByAppendingString: @"\n"]
			dataUsingEncoding: NSASCIIStringEncoding];
		nd=[nd mutableCopy];
		[(NSMutableData *)nd appendData: d];
		d=nd;
		AUTORELEASE(nd);
	}

	if ([md objectForKey: @"References"])
	{
		NSData *nd=[[[@"References: " stringByAppendingString: [md objectForKey: @"References"]] stringByAppendingString: @"\n"]
			dataUsingEncoding: NSASCIIStringEncoding];
		nd=[nd mutableCopy];
		[(NSMutableData *)nd appendData: d];
		d=nd;
		AUTORELEASE(nd);
	}

	/* TODO: this needs to be done in some better way */
	[app_delegate postArticleFrom: self : [d bytes] : [d length]];

	DESTROY(md);
	DESTROY(m);
}

-(void) postedArticle: (BOOL)success
{
	if (!success)
	{
		state=0;
		NSBeep();
	}
	else
	{
		state=2;
		[[self window] performClose: self];
	}
}


-(void) windowWillClose: (NSNotification *)n
{
	[self autorelease];
}

-(void) dealloc
{
	DESTROY(msg_headers);
	[super dealloc];
}

- initWithHeaders: (NSDictionary *)headers  content: (NSString *)content
{
	NSWindow *win;

	win=[[KeyWindow alloc] initWithContentRect: NSMakeRect(100,100,550,500)
		styleMask: NSClosableWindowMask|NSTitledWindowMask|NSResizableWindowMask|NSMiniaturizableWindowMask
		backing: NSBackingStoreRetained
		defer: YES];
	if (!(self=[super initWithWindow: win])) return nil;

	msg_headers=[headers copy];
	state=0;

	{
		NSString *signature=[Pref_Posting postingSignature];
		if (signature)
		{
			content=[[content stringByAppendingString: @"\n-- \n"]
				stringByAppendingString: signature];
		}
	}

	{
		GSVbox *vbox;

		vbox=[[GSVbox alloc] init];
		[vbox setDefaultMinYMargin: 4];
		[vbox setBorder: 2];

		{
			NSScrollView *sv;
			NSTextView *tv;

			sv=[[NSScrollView alloc] initWithFrame: NSMakeRect(0,0,1,1)];
			[sv setHasVerticalScroller: YES];
			[sv setHasHorizontalScroller: YES];
			[sv setBorderType: NSBezelBorder];
			[sv setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];

			text=tv=[[NSTextView alloc] initWithFrame: [[sv contentView] frame]];
			[tv setHorizontallyResizable: NO];
			[tv setVerticallyResizable: YES];
			[tv setEditable: YES];
			[[tv textContainer] setWidthTracksTextView: YES];
			[[tv textContainer] setHeightTracksTextView: NO];
			[[tv textContainer] setContainerSize: NSMakeSize(1e6,1e6)];
			[tv setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];

			if (content)
				[tv setString: content];

			[sv setDocumentView: tv];

			[vbox addView: sv  enablingYResizing: YES];

			[sv release];
			[tv release];
		}

		[vbox addSeparator];

		{
			GSHbox *hbox;
			NSButton *b;
			NSTextField *f;


			hbox=[[GSHbox alloc] init];
			[hbox setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];
			[hbox setDefaultMinXMargin: 2];

			f=[[NSTextField alloc] init];
			[f setStringValue: _(@"Subject:")];
			[f setEditable: NO];
			[f setDrawsBackground: NO];
			[f setBordered: NO];
			[f setBezeled: NO];
			[f setSelectable: NO];
			[f sizeToFit];
			[f setAutoresizingMask: 0];
			[hbox addView: f  enablingXResizing: NO];
			DESTROY(f);

			tf_subject=f=[[NSTextField alloc] init];
			[f setAutoresizingMask: NSViewWidthSizable];
			[f sizeToFit];
			[hbox addView: f  enablingXResizing: YES];
			DESTROY(f);

			[vbox addView: hbox  enablingYResizing: NO];
			DESTROY(hbox);


			hbox=[[GSHbox alloc] init];
			[hbox setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];
			[hbox setDefaultMinXMargin: 2];

			f=[[NSTextField alloc] init];
			[f setStringValue: _(@"Newsgroups (separate with commas):")];
			[f setEditable: NO];
			[f setDrawsBackground: NO];
			[f setBordered: NO];
			[f setBezeled: NO];
			[f setSelectable: NO];
			[f sizeToFit];
			[f setAutoresizingMask: 0];
			[hbox addView: f  enablingXResizing: NO];
			DESTROY(f);

			tf_newsgroups=f=[[NSTextField alloc] init];
			[f setAutoresizingMask: NSViewWidthSizable];
			[f sizeToFit];
			[hbox addView: f  enablingXResizing: YES];
			DESTROY(f);

			[vbox addView: hbox  enablingYResizing: NO];
			DESTROY(hbox);


			hbox=[[GSHbox alloc] init];
			[hbox setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];
			[hbox setDefaultMinXMargin: 2];

			f=[[NSTextField alloc] init];
			[f setStringValue: _(@"From:")];
			[f setEditable: NO];
			[f setDrawsBackground: NO];
			[f setBordered: NO];
			[f setBezeled: NO];
			[f setSelectable: NO];
			[f sizeToFit];
			[f setAutoresizingMask: 0];
			[hbox addView: f  enablingXResizing: NO];
			DESTROY(f);

			tf_from=f=[[NSTextField alloc] init];
			[f setAutoresizingMask: NSViewWidthSizable];
			[f sizeToFit];
			[hbox addView: f  enablingXResizing: YES];
			DESTROY(f);


			b_send=b=[[NSButton alloc] init];
			[b setTitle: _(@"Post")];
			[b sizeToFit];
			[b setTarget: self];
			[b setAction: @selector(post:)];
			[hbox addView: b  enablingXResizing: NO];
			DESTROY(b);


			[vbox addView: hbox  enablingYResizing: NO];
			DESTROY(hbox);
		}

		[win setContentView: vbox];
		[vbox release];
	}


	if ([msg_headers objectForKey: @"Subject"])
		[tf_subject setStringValue: [msg_headers objectForKey: @"Subject"]];

	if ([msg_headers objectForKey: @"Newsgroups"])
		[tf_newsgroups setStringValue: [msg_headers objectForKey: @"Newsgroups"]];

	if ([msg_headers objectForKey: @"From"])
		[tf_from setStringValue: [msg_headers objectForKey: @"From"]];
	else
	{
		NSString *name,*from;
		name=[Pref_Posting postingName];
		from=[Pref_Posting fromAddress];

		if (from)
		{
			if (name)
				[tf_from setStringValue:
					[NSString stringWithFormat: @"\"%@\" <%@>",name,from]];
			else
				[tf_from setStringValue: from];
		}
	}


	[win setTitle: [tf_subject stringValue]];

	[win setDelegate: self];
	[win release];

	return self;
}


/* returns a retained string */
-(NSMutableString *) _quoteString: (NSString *)content  to: (NSMutableString *)astr
{
	NSMutableString *str;
	NSString *line;
	NSArray *lines;
	int i,c;

	lines=[content componentsSeparatedByString: @"\n"];
	c=[lines count];

	if (astr)
		str=astr;
	else
		str=[[NSMutableString alloc] initWithCapacity: [content length]+2*c];

	for (i=0;i<c;i++)
	{
		line=[lines objectAtIndex: i];

		/* don't quote the signature */
		if ([line isEqualToString: @"-- "])
			break;

		if ([line length]>0 && [line characterAtIndex: 0]=='>')
			[str appendString: @">"];
		else
			[str appendString: @"> "];
		[str appendString: line];
		[str appendString: @"\n"];
	}

	return str;
}


- initWithHeaders: (NSDictionary *)headers  quoteContent: (NSString *)content
{
	NSString *str;

	if (!content)
		return [self initWithHeaders: headers  content: nil];

	str=[self _quoteString: content  to: nil];
	self=[self initWithHeaders: headers  content: str];
	DESTROY(str);
	return self;
}

- initWithHeaders: (NSDictionary *)headers
{
	return [self initWithHeaders: headers  content: nil];
}

/* TODO: handle attributation, followup to sender, followup, etc. */
- initWithFollowupToMessage: (Message *)msg
{
	NSDictionary *headers;
	NSString *subject,*references;
	NSString *msgid;
	int i;

	references=[msg headerValueForName: @"References"];
	msgid=[msg messageID];
	if ([msgid characterAtIndex: 0]!='<')
		msgid=[[@"<" stringByAppendingString: [msg messageID] ] stringByAppendingString: @">"];

	if (!references)
		references=msgid;
	else
	{
		references=[[references stringByAppendingString: @" "] stringByAppendingString: msgid];
	}

	subject=[msg subject];
	if ([subject length]>=3 && [subject characterAtIndex: 2]==':')
	{
		for (i=3;i<[subject length];i++)
			if ([subject characterAtIndex: i]>32)
				break;
		subject=[subject substringFromIndex: i];
	}
	subject=[@"Re: " stringByAppendingString: subject];

	headers=[NSDictionary dictionaryWithObjectsAndKeys:
		subject,@"Subject",
		references,@"References",
		[msg headerValueForName: @"Newsgroups"],@"Newsgroups",
		nil];

	{
		NSMutableString *str;

		str=[[NSMutableString alloc] init];

		if ([[msg from] personal] && [[[msg from] personal] length])
			[str appendString: [NSString stringWithFormat: @"%@ wrote:\n",[[msg from] personal]]];
		else
			[str appendString: [NSString stringWithFormat: @"%@ wrote:\n",[[msg from] address]]];

		if ([[msg content] isKindOfClass: [NSString class]])
		{
			NSString *content=(NSString *)[msg content];
			str=[self _quoteString: content  to: str];
		}
		else
			[str appendString: @"> (currently) unquoteable content\n"];

		return [self initWithHeaders: headers  content: str];
		DESTROY(str);
	}

}

@end

