/******************************************************************************
 *
 * 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.
 *
 *
 *	HTMLClient.cpp
 *
 *****************************************************************************/


#include <sol\ApplicationView.h>
#include <sol\PushButton.h>
#include <sol\LabelGadget.h>
#include <sol\TextField.h>
#include <sol\Profile.h>
#include <sol\ScrolledRichText.h>
#include <sol\SocketStream.h>
#include <sol\Font.h>
#include <sol\ClientDC.h>
#include <sol\PaintDC.h>
#include <sol\stdio.h>
#include <sol\InetAddress.h>
#include <sol\URL.h>

#include "HTMLParser.h"
#include "resource.h"

class HttpClient :public ApplicationView {
	int			textHeight;
	LabelGadget		urlLabel;
	TextField		urlField;
	Font			font;
	SocketStream*		sock;
	RichText		sctext;
	HTMLParser		parser;
	void	clear(Action& action);
	long	size(Event& event);
	long	close(Event& event);
	long	paint(Event& event);
	void	recv();
	void	query(Action& action);
	void	receive(const char* host, const char* path, unsigned short port);
	void	readFile(const char* fileName);
  public:
	HttpClient(Application& applet, const char* name, Args& args);
	~HttpClient();
};


HttpClient::HttpClient(Application& applet, const char* name, Args& args)
	:ApplicationView(applet, name, args)
{
	sock = NULL;

	int cx = ::GetSystemMetrics(SM_CXSCREEN);
	int fheight = -12;
	if(cx > 1024) {
		fheight = -16;
	}

	ClientDC dc(this);

	Args ar;
	ar.set(XmNheight, fheight);
	ar.set(XmNcharSet, (ulong)dc.getTextCharsetInfo(NULL));
	font.create(ar);

	HFONT prevFont = dc.select(&font);
	textHeight = dc.getTextHeight();
	dc.select(prevFont);

	ar.reset();
	ar.set(XmNstyle, (ulong)(WS_HSCROLL|WS_VSCROLL|WS_BORDER|ES_AUTOHSCROLL|\
		 ES_AUTOVSCROLL|ES_WANTRETURN|ES_LEFT|ES_MULTILINE));

	sctext.create(this, "", ar);
	sctext.setFont(font);
	RECT rc;
	rc.left = 0;
	rc.top  =0;
	rc.right = 120;
	rc.bottom = 200;

	sctext.setRect(&rc);
	sctext.limitText(100000);
	sctext.setReadOnly();

	sctext.addCallback(XmNmaxTextCallback, this,
		(Callback)&HttpClient::clear, NULL);

	ar.reset();
	urlLabel.create(this, "URL", ar);
	urlLabel.setFont(&font);

	ar.reset();
	urlField.create(this, "",   ar);
	urlField.setFont(font);
	urlField.addCallback(XmNactivateCallback, this,
		(Callback)&HttpClient::query, NULL);

	addCallback(XmNmenuCallback, IDM_CLEAR, this, 
		(Callback)&HttpClient::clear, NULL);
	addCallback(XmNmenuCallback, IDM_EXIT, this, 
		(Callback)&HttpClient::exit, NULL);

	addEventHandler(WM_CLOSE, this, (Handler)&HttpClient::close, NULL);
	addEventHandler(WM_PAINT, this, (Handler)&HttpClient::paint, NULL);

	parser.setViewer(&sctext);
}


HttpClient::~HttpClient() 
{
	delete sock;
}


void HttpClient::clear(Action& action) 
{ 
	urlField.clear();
	sctext.clear(); 
}


long HttpClient::close(Event& event)
{
	return defaultProc(event);
}


void HttpClient::recv()
{			
	sctext.clear();
	int bytes = 0;

	if(!sock) {
		return;
	}
	Boolean err = False;

	// Read header of HTTP response.
	StringBuffer stringBuffer;
	int line = 0; 
	while (sock->readLine(stringBuffer) >2) {
		if (line == 0) {
			Printf("Check Error \r\n");
			const char* reply = stringBuffer.getBuffer();
			if (strstr(reply, "200 OK") ) {
				Printf("HTTP responce OK\r\n");
			}
			else {
				Printf("Error %s", stringBuffer.getBuffer());
				sctext.append(stringBuffer.getBuffer());
				err = True;
				break;
			}
		}
		Printf("H>%s", stringBuffer.getBuffer());
		line++;
		stringBuffer.clear();
	}

	if (err == True) {
		return;
	}	

	// Get the body of response.	
	while(1) {
		StringBuffer buffer;
		buffer.clear();
		int rc = sock->getLine(buffer);
		if (rc <0) break;
		
		if (buffer.getContentSize() >0) {
			const char* string = buffer.getBuffer();
			//Printf(">%s\r\n", string);
			sctext.append(" "); //1999.08.12
			parser.parse((char*)string);
		} 
	}
}



void HttpClient::query(Action& action)
{
	char aurl[256];
	urlField.getText(aurl, sizeof(aurl));

	URL url(aurl);
	const char* prot = url.getProtocol();

	unsigned short port = url.getPort();

	const char* host = url.getHost();
	const char* path = url.getPath();
	Printf("Prot [%s]\r\n", prot);
	Printf("Host [%s]\r\n", host);
	Printf("PORT [%d]\r\n", port);
	Printf("PATH %s\r\n", path);

	if (strcmp(prot, "http") ==0) {
		receive(host, path, port);
	}
	if (strcmp(prot, "file") ==0) {
		const char* fileName = url.getFileName();
		readFile(fileName);	
	}
}



void HttpClient::receive(const char* host, const char* path, unsigned short port)
{
	Printf("receive\r\n");

	sock = new SocketStream(AF_INET, 0);
	InetAddress inetAddress(host, port);

	int rc = sock->connect(inetAddress);

	if(rc) {
		showMessageDialog("HttpClient", "Connection failed", MB_OK);
		// 1999.07.29 Added the following 2 lines
		delete sock;
		sock = null;
		return;
	}

	char buffer[256];
	if (strlen(path) > 0) {
		sprintf(buffer, "GET /%s HTTP/1.0\r\n\r\n", path);
	}
	else {
		sprintf(buffer, "GET / HTTP/1.0\r\n\r\n");
	}
	Printf("Sending %s", buffer);
	int len = strlen(buffer);
	sock->sendAll(buffer, len, 0);

	// Read a reply from server.
	recv();

	sock->shutdown(2);
	delete sock;
	sock = null;
}


void HttpClient::readFile(const char* fileName)
{
	sctext.clear();

	Printf("filename [%s]\r\n", fileName);
	FileStream stream;
	if (stream.openReadOnly(fileName)) {
		char line[256];
		while(stream.getLine(line, sizeof(line)-1) >0) {

			//Printf("%s\r\n", line);
			sctext.append(" "); //1999.08.12
			parser.parse(line);
		}
		stream.close();
	}
}

long HttpClient::paint(Event& event) 
{
	PaintDC dc(this);
	urlLabel.draw(&dc);

	return 0;
}

long HttpClient::size(Event& event)
{
	int w, h;
	event.getSize(w, h);
	int y =  textHeight+8;
	int lw = textHeight*2;
	int top = 4;
	int m   = 4;
	urlLabel.setLocation(m, top);
	int ww, hh;
	urlLabel.getSize(ww, hh);
	urlField.reshape(ww+m, top, w-m*2-lw, y);

	sctext.reshape(0, top+y+m, w, h-top-y-m);

	return 0L;
}


// HttpClient Main
void	Main(int argc, char** argv)
{
	const char* appClass = "HttpClient";
	Application applet(appClass, argc, argv);

	Args args;
	args.set(XmNclassName, appClass);
//	args.set(XmNexStyle, WS_EX_CLIENTEDGE);
	args.set(XmNbackground, (COLOR_BTNFACE+1));
//	args.set(XmNexStyle, WS_EX_CONTROLPARENT);

	HttpClient httpClient(applet, appClass, args);
	httpClient.realize();
	applet.run();	
}

