/*******************************************************************************
*
* This module presents four example PowerWeb Server++ API Hook Functions:
* (all are accessible via the Guided Tour)
*
*	TourCalculation	- used in the Pizza example
*	TourPresentCSV		- used in the Database Viewer example
*	TourDirect			- used in the Direct-Call example
*	TourTree				- used as a more sophisticated Direct-Call example
*
* COPYRIGHT:
*   CompuSource (Pty) Ltd
*   Licensed Materials - Property of CompuSource (Pty) Ltd
*   (C) Copyright CompuSource (Pty) Ltd 1994, 1995.
*   All Rights Reserved
*   Use, duplication, or disclosure restricted by international
*   copyright law.
*
*******************************************************************************/

#pragma	strings(readonly)

#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<math.h>

#include	"Tour.hpp"
#include	"PowerAPI.hpp"

// =========================================================================
// NB these functions are C-interface to allow calls from external programs.

extern	"C"	{

// -------------------------------------------------------------------------
//	This function is called from the order entry form to perform calculations
//	based on data entered. The results are then fed back to the form.
//	Only very simple error checking is performed.

long		TourCalculation	(void*	parcel)
{
	long		cPepperoni;
	long		cHawaiian;
	double	dPrice	= 0.0;
	double	dTax;
	double	dTotal;
	void*		hFormFields;

	// Get a handle to the list of all form fields for quick reference.

	ServerFind(parcel, "Request:/Argument", &hFormFields);

	// Read the two data entry fields - note there is no decoding of
	//	POST arguments - PowerWeb Server++ does this all for us.

	ServerReadInteger(hFormFields, "Pepperoni",	&cPepperoni);
	ServerReadInteger(hFormFields, "Hawaiian",	&cHawaiian);

	//	Perform our computations.

	dPrice += cPepperoni	* 10.95;
	dPrice += cHawaiian	* 12.95;

	dTax 		= floor(dPrice * 10.0) / 100.0;
	dTotal	= dPrice + dTax;

	//	Create three new form fields derived from the existing fields.

	ServerNewFloat(hFormFields, "Price",	dPrice);
	ServerNewFloat(hFormFields, "Tax",		dTax);
	ServerNewFloat(hFormFields, "Total",	dTotal);

	//	Tell the server we had no errors.

	return HOOK_OK;
}

// -------------------------------------------------------------------------
//	This function is called whenever a ".CSV" file is loaded from the
//	Tour database directory. It presents comma-separated-variable files
//	in an HTML table.
//	Only very simple error checking is performed.

long		TourPresentCSV		(void*	parcel)
{
	char		aszFile[_MAX_PATH];
	FILE*		csv;
	char		buffer[512];
	void*		hResult;
	char*		pszBegin;
	char*		pszComma;

	//	Query the current physical resource being accessed.

	ServerReadText(parcel, "Request:/Resource", aszFile, sizeof(aszFile));

	//	Open the file so that we can translate it into HTML.

	csv = fopen(aszFile, "r");

	if (csv == 0) {
		ServerWriteInteger(parcel, "Request:/StatusCode", 400);
		return HOOK_ERROR;
	}

	//	Get a handle to the HTML result output variable.

	ServerFind(parcel, "Request:/Result", &hResult);

	//	Output the HTML preamble.

	ServerAppendText(hResult, 0, "<html><body><h2>Tabular View of ");
	ServerAppendText(hResult, 0, aszFile);
	ServerAppendText(hResult, 0, "</h2><table border=1>");

	//	Process each line (record) within the database file.

	while (fgets(buffer, sizeof(buffer), csv)) {
		ServerAppendText(hResult, 0, "<tr>");

		// Scan for each field and output it with a <td> prefix.

		pszBegin = buffer;

		while ((pszComma = strchr(pszBegin, ',')) != 0) {
			*pszComma = 0;

			//	Remove surrounding quotes, if any.

			if (*pszBegin == '"' && pszComma[-1] == '"') {
				pszBegin++;
				pszComma[-1] = 0;
			}

			ServerAppendText(hResult, 0, "<td>");
			ServerAppendText(hResult, 0, pszBegin);

			pszBegin = pszComma + 1;
		}

		//	Output the last field in the record.

		pszComma = pszBegin + strlen(pszBegin);
		if (pszComma[-1] == '\n') pszComma--;

		if (*pszBegin == '"' && pszComma[-1] == '"') {
			pszBegin++;
			pszComma[-1] = 0;
		}

		ServerAppendText(hResult, 0, "<td>");
		ServerAppendText(hResult, 0, pszBegin);
		ServerAppendText(hResult, 0, "\n");
	}

	fclose(csv);

	//	Output the closing HTML code.

	ServerAppendText(hResult, 0, "</table></body></html>");

	return HOOK_OK;
}

// -------------------------------------------------------------------------
//	This function is called directly from a URL without needing an
//	associated resource to manage it.
//	It is very simple - outputs "Hello World". Our apologies for
//	this over-used example, but script writing doesn't get more complex!

long		TourDirect	(void*	parcel)
{
	void*		hResult;

	//	Get a handle to the HTML result output variable.
	ServerFind(parcel, "Request:/Result", &hResult);

	// Output our message
	ServerAppendText(hResult, 0, "Hello World, from a Direct C Interface.");

	return HOOK_OK;
}

// -------------------------------------------------------------------------
//	Internal function called recursively by TourTree().

void		TourTreeRecursion(void* hRoot, void* hResult, int iLevel)
{
	unsigned long		iKind;
	char					buffer[256];

	// If not at the root, display the hRoot Variable's name and value.

	if (iLevel > 0) {
		ServerName(hRoot, buffer, sizeof(buffer));
		ServerAppendText(hResult, 0, "<li>");
		ServerAppendText(hResult, 0, buffer);

		ServerAppendText(hResult, 0, " = ");

		ServerReadText(hRoot, 0, buffer, sizeof(buffer));
		ServerAppendText(hResult, 0, (strlen(buffer) == 0) ? "(None)" : buffer);
	}

	// If the hRoot Variable is a list, display it recursively.

	ServerKind(hRoot, &iKind);

	if (iKind == 5) {
		void*		hNext;

		if (ServerChild(hRoot, &hNext) == ERR_NONE) {
			ServerAppendText(hResult, 0, "<ul>");

			do {
				TourTreeRecursion(hNext, hResult, iLevel+1);
			} while (ServerSibling(hNext, &hNext) == ERR_NONE);

			ServerAppendText(hResult, 0, "</ul>\n");
		}
	}
}

// -------------------------------------------------------------------------
//	Recursively dump a multi-level list representation of the entire
//	tree of Variables, or of a sub-tree if there is an argument to the URL.
//	Example: "http://127.0.0.1/bin/tour!TourTree?Request:/"

long		TourTree	(void*	parcel)
{
	void*		hResult;
	void*		hRoot;
	char		buffer[256];

	//	Get a handle to the HTML result output variable.

	ServerFind(parcel, "Request:/Result", &hResult);

	// Read the argument to the URL (if any)

	ServerReadText(parcel, "Request:/ArgumentText", buffer, sizeof(buffer));

	// If no argument given, use a default of the Configuration database.

	if (strlen(buffer) == 0)
		strcpy(buffer, "Config:/");

	// Test whether the requested root of the Variable tree actually exists.

	if (ServerFind(parcel, buffer, &hRoot) != ERR_NONE) {
		ServerAppendText(hResult, 0, "Failed to Find the Requested Variable Directory: ");
		ServerAppendText(hResult, 0, buffer);
	}
	else {
		ServerAppendText(hResult, 0, "<h2>Tree of Variables Under: ");
		ServerAppendText(hResult, 0, buffer);
		ServerAppendText(hResult, 0, "</h2>\n");

		TourTreeRecursion(hRoot, hResult, 0);
	}

	return HOOK_OK;
}

// -------------------------------------------------------------------------

}

