#pragma once

#ifndef APL_NO_LDAP_DEFINE
class LDAPMessage;
class LDAP;
#endif

#ifndef APL_LDAP_NOAUTOLIB
#ifdef _DEBUG
#ifdef _UNICODE
#pragma comment (lib,"aplLDAP_ud.lib")
#else // #ifdef _UNICODE
#pragma comment (lib,"aplLDAP_d.lib")
#endif // #ifdef _UNICODE
#else
#ifdef _UNICODE
#pragma comment (lib,"aplLDAP_u.lib")
#else // #ifdef _UNICODE
#pragma comment (lib,"aplLDAP.lib")
#endif // #ifdef _UNICODE
#endif
#endif


#ifdef APL_LDAP_NOAUTOLIB
#define CLASS_DECL_APL_LDAP  _declspec(dllexport)
#else
#define CLASS_DECL_APL_LDAP  _declspec(dllimport)
#endif

class CLASS_DECL_APL_LDAP CaplLDAP
{
public:
	CaplLDAP(void);
	~CaplLDAP(void); //Вызывает Disconnect

	LPCTSTR GetLastError(); //Возвращает название последней ошибки.

	static bool GetCurrentWindowsUser(CString &user);   // Возвращяет имя текущего пользователя windows
	static bool GetCurrentWindowsDomainName(CString &domain); // Возвращяет текущий домен, в котороый вошел пользователь windows
	static bool GetCurrentWindowsDomainServer(CString &server); // Возвращяет сервер домена, через котороый вошел пользователь windows


	// Инициализирует LDAP, устанавливает соединение с серверм.  (Никакие права не проверяются. По сути, просто проверяет наличие сервера) 
	// После надо  вызывать Connect() или TestConnect()
	// Если порт ==0, то используется 389.  Можно указать порт в сервере как server:port
	bool Init(LPCTSTR domain, LPCTSTR server, ULONG port=0);

	// Проверяет соединение под пользователем. Соединение не запоминается.  (перед вызыоыом должен быть вызван Init())
	// Если user_name==0, то устанавливает соединенеие под текущим пользователем windows
	// Возвращяет true, если успешно.
	// (отключено!)Если соединение не установлено, пытается нати пользователя в домене, чтобы выяснить неверный пароль или пользователь.
	// Результат пишет в m_s_last_error
	bool TestUserConnect(LPCTSTR user_name, LPCTSTR password);  
	
	//Устанавливает соединение под конкретным пользователем (перед вызыоыом должен быть вызван Init())
	// Если user_name==0, то устанавливает соединенеие под текущим пользователем windows
	// Возвращяет true, если успешно.
	bool Connect(LPCTSTR user_name, LPCTSTR password);
	
	// Закрывает соединение, Очищает память. Вызывается деструктором.
	void Disconnect(); 
	

	bool FindUser(LPCTSTR user_name);  //Ищет пользователя в домене  Возвращает 0, если не найден. Или первый попавшийся из найденных
	bool GetObjectAttr(LPCTSTR attr, CString &value); // Читает атрибут ранее найденного объекта. Если значений несколько - они разделяются ';'
	
	
	bool GetUserInfo(LPCTSTR user_name,CString &info);  // Все данные о пользователе (функция для отладки)

	bool Search(LPCTSTR BaseDN, LPCTSTR filter, CString &info); // Поиск (функция для отладки)

	static CString GetLDAPErrorDescr(ULONG errcode);

	void SetALDMode(bool bALDMode){m_bALDMode = bALDMode;}
	bool GetALDMode(){return m_bALDMode;}

protected:
	bool bIsConnect; // Установлено ли соединение
	bool m_bALDMode;        // Режим работы с ALD (true для ALD и false для AD). Работает только при АНОНИМНОМ подключении!!
	CString m_s_last_error;
	CString m_domain_dns;  // Домен в формате DNS: "ad.ofc.gamma.ru"
	CString m_domain_ldap;  // Домен в формате LDAP: "DC=ad,DC=ofc,DC=gamma,DC=ru"
	CString m_server;
	ULONG m_port;

	LDAP *m_pLdapConnection;
	LDAPMessage *m_answer, *m_entry;

	void SetLDAPError(LPCTSTR mess);
	void SetLDAPError(LPCTSTR mess, ULONG code);
};
