#ifndef FTP_HELPER_H
#define FTP_HELPER_H

#include <string>
#include <vector>
#include <fstream>
#include <iostream>

class FtpHelper
{
public:
	typedef std::vector<std::string> FileList;

	class FtpException
	{
	public:
		FtpException(const std::string &error, CURLcode code) : m_error(error), m_curlErrorCode(code) 
		{}

		FtpException(const std::string &error) : m_error(error)
		{}

		std::string ToString() 
		{
			return m_error + curl_easy_strerror(m_curlErrorCode);
		}

	private:
		std::string m_error;
		CURLcode m_curlErrorCode;
	};
	
	enum StatusCode
	{
		STATUS_CODE_OK,
		STATUS_CODE_ERROR,
	};

	class StatusCodeHelper
	{
	public:
		StatusCodeHelper(StatusCode statusCode = STATUS_CODE_OK, const std::string &statusText = "") : m_statusCode(statusCode), m_statusText(statusText){}
		StatusCodeHelper(const StatusCodeHelper &statusCodeHelper)
		{
			m_statusText = statusCodeHelper.m_statusText;
			m_statusCode = statusCodeHelper.m_statusCode;
		}

		friend bool operator == (const StatusCode &statusCode, const StatusCodeHelper &statusCodeHelper) 
		{
			return (statusCodeHelper.m_statusCode == statusCode);
		}

		friend bool operator != (const StatusCode &statusCode, const StatusCodeHelper &statusCodeHelper) 
		{
			return !(statusCodeHelper.m_statusCode == statusCode);
		}

		const std::string &ToString() const
		{
			return m_statusText;
		}
	private:
		std::string m_statusText;
		StatusCode m_statusCode;
	};

	FtpHelper(const std::string &url, bool verbose = false);
	~FtpHelper();

	StatusCodeHelper GetFileList(FileList &fileList, bool includeDirectories = false);
	StatusCodeHelper GetFile(const std::string &filename);
	StatusCodeHelper DeleteFile(const std::string &filename);

private:
	class CallBackData
	{
	public:
		virtual size_t AppendData(void *ptr, size_t size) = 0;
	};

	class FileListCallBackData : CallBackData
	{
	public:
		virtual size_t AppendData(void *ptr, size_t size);
		StatusCodeHelper GetFileList(FileList &fileList, bool includeDirectories);
		
	private:
		std::string m_data;
	};

	class FileCallBackData : CallBackData
	{
	public:
		FileCallBackData(const std::string &filename, int fileSize = 0) ;
		virtual size_t AppendData(void *ptr, size_t size);

	private:
		std::ofstream m_file;
	};

	class FileDeleteCallBackData : CallBackData
	{
	public:
		virtual size_t AppendData(void *ptr, size_t size)
		{
			return size;
		}
	
	};

	static size_t CallbackFunction(void *ptr, size_t size, size_t nmemb, void *stream);

	CURL *m_curl;
	std::string m_url;
	bool m_verbose;
};


#endif //FTP_HELPER_H