// $Id: CTranslateTask.cc,v 1.16 2003/05/30 05:27:13 ta_muto Exp $

#include <views/CTranslateTask.h>
#include <views/CXmlFile.h>
#include <views/CXslFile.h>

#include <CRequest.h>
#include <CWaxLibs.h>

wax::CTranslateTask::CTranslateTask()
{
	xmlSource = NULL;
	xslSource = NULL;
	
	result = NULL;
}

wax::CTranslateTask::~CTranslateTask()
{
	if(xmlSource != NULL)	delete xmlSource;
	if(xslSource != NULL)	delete xslSource;
	
	if(result != NULL)	xmlFreeDoc(result);
}

bool wax::CTranslateTask::parse(CEnvironment* runenv, xmlNodePtr cur)
{
	xmlNsPtr ns = xmlSearchNsByHref(runenv->getDocPtr(), cur, CEnvironment::WAX);

	cur = cur->children;
	while(cur != NULL) {
		if(cur->ns == ns) {
			if(!xmlStrcmp(cur->name, (const xmlChar*) "source")) {
				xmlSource = parseSourceTag(runenv, cur, ns);
			} else if(!xmlStrcmp(cur->name, (const xmlChar*) "stylesheet")) {
				xslSource = parseStylesheetTag(runenv, cur, ns);
			} else if(!xmlStrcmp(cur->name, (const xmlChar*) "transfer")) {
				xslSource = parseStylesheetTag(runenv, cur, ns);
			}
		}
		cur = cur->next;
	}
	if(xmlSource == NULL || xslSource == NULL) {
		IError::message(ERR_PARSETRANSLATE, LOCATION);
		return false;
	}
	return true;
}

bool wax::CTranslateTask::execute()
{
	if(xslSource->retrieve() == false) {
		return false;
	}
	if(xmlSource->retrieve() == false) {
		return false;
	}
	result = xsltApplyStylesheet(
		xslSource->getXslDocument(),
		xmlSource->getXmlDocument(),
		getXslParameter());
	if(result == NULL)	return false;
	return true;
}

void wax::CTranslateTask::output(IWriter* writer)
{
#if LE==1
	xsltSaveResultToFile(writer->getFP(), result, xslSource->getXslDocument());
#else
	xmlChar* buffer;
	int length;
	
	xsltSaveResultToString(&buffer, &length, result, xslSource->getXslDocument());
	writer->write((const char*) buffer, length);
	xmlFree(buffer);
#endif
}

wax::IXmlSource* wax::CTranslateTask::parseSourceTag(CEnvironment* runenv, xmlNodePtr cur, xmlNsPtr ns)
{
	CXmlStr uri(xmlGetProp(cur, (const xmlChar*) "uri"));
	if(uri.value() != NULL) {
		CXmlStr path(runenv->makePath(uri.value()));
		return new CXmlFile(runenv->getReader(path.value()));
	}
	return NULL;
}

wax::IXslSource* wax::CTranslateTask::parseStylesheetTag(CEnvironment* runenv, xmlNodePtr cur, xmlNsPtr ns)
{
	CXmlStr uri(xmlGetProp(cur, (const xmlChar*) "uri"));
	if(uri.value() != NULL) {
		CXmlStr path(runenv->makePath(uri.value()));
		IXslSource* ret = new CXslFile(runenv->getReader(path.value()));

		if(parseStylesheetParams(runenv, cur, ns) == false) {
			delete ret;
			return NULL;
		}
		
		CXmlStr attrEnv(xmlGetProp(cur, (const xmlChar*) "environment"));
		if(checkBoolean(attrEnv.value(), false) == true) {
			supportEnvironment();
		}
		return ret;
	}
	return NULL;
}

bool wax::CTranslateTask::parseStylesheetParams(CEnvironment* runenv, xmlNodePtr cur, xmlNsPtr ns)
{
	cur = cur->children;
	while(cur != NULL) {
		if(cur->ns == ns) {
			if(!xmlStrcmp(cur->name, (const xmlChar*) "with-param")) {
				CXmlStr name(xmlGetProp(cur, (const xmlChar*)"name"));
				if(name.value() == NULL) {
					IError::message(ERR_ATTRIBUTE, "with-param::name");
					return false;
				}
				CXmlStr fixed(xmlGetProp(cur, (const xmlChar*) "fixed"));
				CXmlStr value(xmlGetProp(cur, (const xmlChar*)"value"));
				if(value.value() == NULL) {
					xmlChar* content = NULL;
					if(CWaxLibs::parseAsContent(runenv, cur->children, ns, content) == false) {
						return false;
					}
					addParameter(name.value(), content, checkBoolean(fixed.value(), false));
				} else {
					addParameter(name.value(), value.value(), checkBoolean(fixed.value(), false));
				}
			}
		}
		cur = cur->next;
	}
	matchParameter(runenv);
	return true;
}

void wax::CTranslateTask::matchParameter(CEnvironment* runenv)
{
	CRequest* request = runenv->getRequest();
	if(request == NULL)	return;

	CParameterItem* seek = (CParameterItem*) params.getHead();
	while(seek != NULL) {
		if(seek->getFixed() == false) {
			CParameterItem* item = request->findParameter(seek->getName());
			if(item != NULL) {
				seek->setOriginalValue(item->getOriginalValue());
			}
		}
		seek = (CParameterItem*)seek->getNext();
	}
}

const char** wax::CTranslateTask::getXslParameter()
{
	int count = 0;
	CParameterItem* cur = (CParameterItem*)params.getHead();
	while(cur != NULL) {
		paramsArray[count++] = (char*)cur->getName();
		paramsArray[count++] = (char*)cur->getValue();
		if(count >= MAX_PARAMETERS) {
			IError::message(ERR_OVERMAXPARAMS, "MAX_PARAMETERS = %d", MAX_PARAMETERS);
			return NULL;
		}
		cur = (CParameterItem*)cur->getNext();
	}
	paramsArray[count] = NULL;
	return (const char**)paramsArray;
}

void wax::CTranslateTask::addParameter(const xmlChar* name, const xmlChar* value, bool fixed)
{
	params.addItem(new CParameterItem(name, value, fixed));
}

void wax::CTranslateTask::supportEnvironment()
{
	addEnvironment("HTTP_ACCEPT_LANGUAGE");
	addEnvironment("HTTP_REFERER");
	addEnvironment("HTTP_USER_AGENT");
	addEnvironment("REMOTE_ADDR");
	addEnvironment("REMOTE_HOST");
	addEnvironment("REMOTE_USER");
}

void wax::CTranslateTask::addEnvironment(char* env)
{
	addParameter((const xmlChar*)env, (const xmlChar*)getenv(env), true);
}
