/******************************************************************************
 *
 * Copyright (c) 1999	TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *	SolMailer.cpp
 *
 *****************************************************************************/


#include <sol\ApplicationView.h>
#include <sol\TextField.h>
#include <sol\LabelGadget.h>
#include <sol\Static.h>
#include <sol\PushButton.h>
#include <sol\ScrolledRichText.h>
#include <sol\DesktopWindow.h>
#include <sol\Profile.h>
#include <sol\Font.h>
#include "resource.h"
#include <sol\PaintDC.h>
#include <sol\PopupView.h>
#include <sol\Clientdc.h>
#include <sol\StringList.h>
#include <sol\StringBuffer.h>
#include <sol\StringTokenizer.h>
#include <sol\Exception.h>

#include "SMTPClient.h"
#include "Mail.h"
#include "ConfigDialog.h"


class SolMailer :public ApplicationView {
	Font*               font;
	LabelGadget*        subject;
	LabelGadget*        to;
	LabelGadget*        cc;

	RichText*           textf;
	ScrolledRichText*   tolist;
	ScrolledRichText*   cclist;
	ScrolledRichText*	bcclist;	// Currently unused.

	ScrolledRichText*	sctext;
	PopupView*          setupdlg;
	int                 textHeight;
	ConfigDialog*		configDialog;

	String				server;
	String				domain;
	String				address;

	void	clear(Action& action);
	long	size(Event& event);
	long	close(Event& event);
	long	paint(Event& event);
	void	send(Action& action);
	void	config(Action& action);
	void	updateConfig(Action& action);	
	void	loadProfile();

	int		getStringList(Text* text, StringList& list);

 public:
	SolMailer(Application& applet, const char* name, Args& args);
	~SolMailer();
};


SolMailer::SolMailer(Application& applet, const char* name, Args& args)
	:ApplicationView(applet, name, 
		args.set(XmNbackground, (ulong)(COLOR_BTNFACE+1))
		    .set(XmNexStyle, (ulong)WS_EX_CLIENTEDGE)	)
{
	Args ar;
	ar.reset();
	ar.set(XmNheight, (-12));
	font = new Font(ar);
	ClientDC dc(this);
	HFONT prevFont = (HFONT)dc.select(&font);
	textHeight = dc.getTextHeight();
	dc.select(prevFont);

	subject = new LabelGadget(this, "Subject", ar);
	subject -> setFont(font);

	ar.reset();
	to = new LabelGadget(this, "TO", ar);
	to -> setFont(font);

	ar.reset();
	cc = new LabelGadget(this, "CC", ar);
	cc -> setFont(font);

	ar.reset();
	textf = new RichText(this, "",   ar);
	textf -> setFont(font);

	ar.reset();
	ar.set(XmNstyle, (ulong)ES_MULTILINE);
	tolist = new ScrolledRichText(this, "", ar);
	tolist -> setFont(font);

	ar.reset();
	ar.set(XmNstyle, (ulong)ES_MULTILINE);
	cclist = new ScrolledRichText(this, "", ar);
	cclist -> setFont(font);

	ar.reset();
	ar.set(XmNstyle, (ulong)ES_MULTILINE);
	bcclist = new ScrolledRichText(this, "", ar);
	bcclist -> setFont(font);

	ar.reset();
	ar.set(XmNstyle, (ulong)ES_MULTILINE);
	sctext = new ScrolledRichText(this, "", ar);
	sctext -> setFont(font);

	sctext -> exLimitText(100*1000);

	addCallback(XmNmenuCallback, ID_NEW, this, (Callback)&SolMailer::clear, NULL);

	addCallback(XmNmenuCallback, ID_SEND, this, (Callback)&SolMailer::send, NULL);

	addCallback(XmNmenuCallback, ID_EXIT, this, (Callback)&SolMailer::exit, NULL);

	addCallback(XmNmenuCallback, ID_CONFIG, this, (Callback)&SolMailer::config, NULL);

	addEventHandler(WM_CLOSE, this,(Handler)&SolMailer::close, NULL);

	addEventHandler(WM_PAINT, this, (Handler)&SolMailer::paint, NULL);

	restorePlacement();

	ar.reset();
	ar.set(XmNwidth, 340);
	ar.set(XmNheight, 200);
	ar.set(XmNstyle, (ulong)WS_THICKFRAME);
	configDialog = new ConfigDialog(this, "Configuration", ar);
	configDialog ->addOkCallback(this, (Callback)&SolMailer::updateConfig);

	loadProfile();
}


SolMailer::~SolMailer()
{ 
	delete font;
	delete subject;
	delete to;
	delete cc;
	delete textf;
	delete tolist;
	delete cclist;
	delete bcclist;
	delete sctext;
	delete configDialog;
}


void SolMailer::loadProfile()
{
	Profile profile("SolMailer");
	char server1[256];
	profile.get("SolMailer", "Server", "", server1, sizeof(server1)-1);
	
	char domain1[256];
	profile.get("SolMailer", "User", "", domain1, sizeof(domain1)-1);

	char address1[256];
	profile.get("SolMailer", "Address", "", address1, sizeof(address1)-1);

	server  = server1;
	domain    = domain1;
	address = address1;
}


void SolMailer::config(Action& action)
{
	configDialog -> setServer((const char*)server);
	configDialog -> setUser((const char*)domain);
	configDialog -> setAddress((const char*)address);

	configDialog -> popup(action);
}


void SolMailer::updateConfig(Action& action)
{
	char server1[256];
	configDialog ->getServer(server1, sizeof(server1));

	char domain1[256];
	configDialog ->getUser(domain1, sizeof(domain1));

	char address1[256];
	configDialog ->getAddress(address1, sizeof(address1));
	Printf("SolMailer::updateConfig\r\n");

	if (strlen(server1) > 0 && strlen(domain1) > 0 && strlen(address1)>0) {
		Profile profile("SolMailer");
		profile.set("SolMailer", "Server", server1);
		profile.set("SolMailer", "User",   domain1);
		profile.set("SolMailer", "Address", address1);

		Printf("%s  %s %s \r\n", server1, domain1, address1);
		server  = server1;
		domain   = domain1;
		address = address1;

		configDialog -> popdown(action);
	}
}


void SolMailer::clear(Action& action)
{
	int rc =MessageBox(NULL, "Create a new mail.", "New", MB_OKCANCEL);
	if(rc == IDOK) {
		sctext -> setText("");
		tolist -> setText("");
		cclist -> setText("");
		bcclist -> setText("");
		textf  -> setText("");
	}
}


int SolMailer::getStringList(Text* text, StringList& list)
{
	int rc = 0;
	
	char* buffer = text -> getText();

	if (buffer && strlen(buffer)) {
		char* ptr = buffer;
		// Replace "\r\n" by ", ".
		while (ptr = strstr(ptr, "\r\n") ) {
			*ptr = ',';
			*(ptr+1) = ' ';
			ptr = ptr + 2;
		}

		StringTokenizer tokenizer(buffer);

		tokenizer.clearSeparator();
		tokenizer.addSeparator(',');
		tokenizer.addSeparator(';');
		String token = "";
		// Get a token and append it to the list.
		while (tokenizer.getToken(token)) {
			if (token.getLength() >0) {
				list.add((const char*)token);
				rc++;
			}
			token = "";
		}
		delete [] buffer;
	}
	return rc;
}


void SolMailer::send(Action& action)
{
	int rc =MessageBox(NULL, "Send this mail.", "Send", MB_OKCANCEL);
	if(rc == IDOK) {
		StringList tos, ccs, bccs;

		getStringList(tolist,  tos);
		getStringList(cclist,  ccs);
		getStringList(bcclist, bccs);

		if (tos.getLength() == 0) {
			showMessageDialog("Error", "TO receiver is empty");
			return;
		}

		char* subject = textf ->  getText();
		char* body    = sctext -> getText();
		const char* sender = (const char*)address;

		Mail mail(subject, sender, tos, ccs, bccs, body);
	//	delete [] subject;
	//	delete [] body;

		SMTPClient client((const char*)server, 
			(const char*)domain, mail);
	
		client.start();
		client.wait();
		int result = client.getResult();
		if (result == 0) {
			const char* error = client.getError();
			showMessageDialog("Error", error);
		} else {
			char buff[256];
			sprintf(buff, "Sent %d mail(s)", result);
			showMessageDialog("SolMailer", buff);
		}
	}
}


long SolMailer::close(Event& event)
{
	savePlacement();

	return defaultProc(event);
}


long SolMailer::paint(Event& event) 
{
	PaintDC dc(this);
	subject -> draw(&dc);
	to -> draw(&dc);
	cc -> draw(&dc);

	return NULL;
}

long SolMailer::size(Event& event)
{

	LPARAM pos = event.getLParam();
	int h = HIWORD(pos);
	int w = LOWORD(pos);
	int x = 80;
	int y1 = textHeight+4;	//30;
	int y2 = textHeight*2+4;
	int lw = textHeight*2; //40;
	int top = 4;
	int m  = 4;
	
	subject -> setLocation(m, top);
	int ww, hh;
	subject -> getSize(ww, hh);
	textf -> reshape(m+ww, top, w-m*2-ww, y1);
	to -> setLocation(m, top+y1+m);

	tolist -> reshape(m+ww,top+y1+m, w-m*2-ww, y2);
	cc -> setLocation(m, top+y1+m+y2+m);
	cclist -> reshape(m+ww, top+y1+m+y2+m, w-m*2-ww, y2);

	sctext -> reshape(m, top+y1+m+(y2+m)*2, w-m*2, 
			h-top-y1-m-(y2+m)*2-m);
	return NULL;
}


// SolMailer Main
void	Main(int argc, char** argv)
{
	const char* appClass = "SolMailer";
	Application applet(appClass, argc, argv);
	Args args;
	args.set(XmNexStyle, (ulong)WS_EX_CONTROLPARENT);
	SolMailer solMailer(applet, appClass, args);
	solMailer.realize();
	applet.run();
}
