/*******************************************************************************
 * Copyright (c) 2005, 2006 Intel Corporation, IBM.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Kevin P O'Leary , Intel - Initial API and Implementation (Based on the Java
 *                                API implementation by IBM)
 *
 * $Id: FileTransfer.cpp,v 1.10 2006/02/10 19:54:16 vnaikawadi Exp $
 *******************************************************************************/ 

#include <stdio.h>
#include <iostream>
#include "tptp/client/FileTransfer.h"
#include "tptp/client/ControlMessage.h"
#include "tptp/client/Constants.h"
#include "tptp/client/FileDataProcessor.h"
#include "tptp/TPTPCommon.h"
#include "tptp/TPTPUtils.h"
#include "tptp/dime.h"



using namespace std;
using namespace TPTP::Client;

#define BLOCK_SIZE 1024


FileTransfer::FileTransfer()
{
	dataInit = 0;
	debugOn = 1;
}

FileTransfer::FileTransfer(tptp_int32 id, char* name) : Collector(id, name)
{
	dataInit = 0;
	debugOn = 1;
}

FileTransfer::FileTransfer(char* name) : Collector(name)
{
	dataInit = 0;
	debugOn = 1;
}



FileTransfer::~FileTransfer()
{

}


void FileTransfer::startFileDataProcessor()
{
	if (this->dataInit == 0) {
		createDataConnection(3);
		this->dataProcessor = new FileDataProcessor();
		this->dataConnectionId = this->addDataListener(dataProcessor);
		this->dataInit = 1;
	}
}


tptp_int32 is_text(const char *fileName) 
{
	tptp_int32 len = strlen(fileName);
	char* new_str;

	if (len < 4) {
		return false;
	}
	new_str = (char *) tptp_malloc(len -4);
	strcpy(new_str, fileName+len-4);

	if ( isEqualString(new_str, ".txt"))
	{
		return true;
	} else {
		return false;
	}
}

tptp_int32 FileTransfer::getFile(char *localFile, char *remoteFile)
{
	char* getCmdFormat = "<getFile iid=\"org.eclipse.tptp.FileTransferAgent\"><localFile>%s</localFile><remoteFile>%s</remoteFile></getFile>";
	char getCmd[1024];
	FILE* fp;

	/* First establish the dataPath if not already there */
	this->startFileDataProcessor();

	/* Next create the local file */
	/*
	if( is_text(localFile)) {
		fp = fopen(localFile, "w");
	} else {
		fp = fopen(localFile, "wb");
	}
	*/
	fp = fopen(localFile, "wb");

	if (fp == NULL) {
		cout<<"FileTransfer::getFile() failed to create local "<<localFile<<endl;
		return -1;
	}

	this->dataProcessor->initializeFileTransfer(localFile, fp);

	/* Send the getFile command to the Agent */
	sprintf(getCmd, getCmdFormat, localFile, remoteFile);
	this->sendCommand(getCmd, NULL);

	this->dataProcessor->waitForFileComplete(localFile);

	fclose(fp);

	return 0;
}

tptp_int32 FileTransfer::sendFileData(char *buffer, tptp_int32 bufferLength, tptp_int32 recType, char *fileName) 
{
	DIME_HEADER_PTR_T dp;
	tptp_int32 dimeLength;
	tptp_int32 rc;

	dimeLength = MAKE_DIME_FILE_TRANSFER(&dp, fileName, bufferLength);

	if (recType == DIME_MESSAGE_START_END) {
		DIME_START(dp);
		DIME_END(dp);
	} else if (recType == DIME_MESSAGE_START) {
		DIME_START(dp);
	} else if (recType == DIME_MESSAGE_END) {
		DIME_END(dp);
	}

	MAKE_NBO_DIME_HEADER((char *) dp);
	rc = sendData(buffer, bufferLength, (char *) dp, dimeLength);

	return rc;
}

tptp_int32 FileTransfer::putFile(char *localFile, char *remoteFile)
{
	char* putCmdFormat = "<putFile iid=\"org.eclipse.tptp.FileTransferAgent\"><localFile>%s</localFile><remoteFile>%s</remoteFile></putFile>";
	char putCmd[1024];

	char buffer[BLOCK_SIZE+1];
	FILE *fp;
	tptp_int32 i;
	tptp_int32 ret;
	tptp_int32 n;
	tptp_int32 recType;
	tptp_int32 fileSize;
	tptp_int32 tot=0;


	if (debugOn)
	cout<<"Sending putFile() command"<<endl;

	/* First establish the dataPath if not already there */
	this->startFileDataProcessor();
	/* Send the putFile command to the Agent */
	sprintf(putCmd, putCmdFormat, localFile, remoteFile);
	this->sendCommand(putCmd, NULL);
	/*
	if( is_text(localFile)) {
		fp = fopen(localFile, "r");
	} else {
		fp = fopen(localFile, "rb");
	}
	*/
	fp = fopen(localFile, "rb");
	if (fp == NULL) {
		return 0;
	}
	
	fileSize = getFileSize(localFile);
	i =0;
	while ((n = fread((void *) buffer, 1, BLOCK_SIZE, fp)) > 0) {
		tot=tot+n;
		if (i==0) {
			recType = DIME_MESSAGE_START;
		} else {
		 	recType = DIME_MESSAGE_MIDDLE;
		}
		if (tot == fileSize) {
			if (i == 0) {
				recType = DIME_MESSAGE_START_END;
			} else {
				recType = DIME_MESSAGE_END;
			}
		}
		ret = sendFileData(buffer, n, recType, remoteFile);
		i++;
	}
	if (fileSize == 0) 
	{
		recType = DIME_MESSAGE_START_END;
		ret = this->sendFileData(buffer, 0, recType, remoteFile);
	}

	if (debugOn)
	cout<< "FileTransfer putFile close file " <<endl;

	fclose(fp);	
	 
	return 0;
}

tptp_int32 FileTransfer::deleteFile(char *remoteFile)
{
	char* deleteCmdFormat = "<deleteFile iid=\"org.eclipse.tptp.FileTransferAgent\"><remoteFile>%s</remoteFile></deleteFile>";
	char deleteCmd[1024];

	if (debugOn)
	cout<<"Sending deleteFile() command"<<endl;

	/* Send the deleteFile command to the Agent */
	sprintf(deleteCmd, deleteCmdFormat, remoteFile);
	this->sendCommand(deleteCmd, NULL);

	return 0;
}
