//! \~\file pinetworkaddress.h
//! \~\ingroup Types
//! \~\brief
//! \~english Network address
//! \~russian Сетевой адрес
/*
    PIP - Platform Independent Primitives
    Network address
    Ivan Pelipenko peri4ko@yandex.ru

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef PINETWORKADDRESS_H
#define PINETWORKADDRESS_H


#include "pistring.h"


//! \~\ingroup Types
//! \~\brief
//! \~english Network address, IP and port.
//! \~russian Класс для работы с сетевым адресом, IP и портом.
class PIP_EXPORT PINetworkAddress {
	friend class PIEthernet;

public:
	//! \~english Contructs %Address with binary representation of IP and port
	//! \~russian Конструктор для создания объекта адреса с бинарным представлением IP и порта
	PINetworkAddress(uint ip = 0, ushort port = 0);

	//! \~english Contructs %Address with string representation "i.i.i.i:p"
	//! \~russian Конструктор для создания объекта адреса с представлением IP и порта в виде строки "i.i.i.i:p"
	PINetworkAddress(const PIString & ip_port);

	//! \~english Contructs %Address with IP string representation "i.i.i.i" and port
	//! \~russian Конструктор для создания объекта адреса с представлением IP в виде строки "i.i.i.i" и порта
	PINetworkAddress(const PIString & ip, ushort port);

	//! \~english Returns binary IP
	//! \~russian Возвращает IP-адрес в бинарном виде
	uint ip() const { return ip_; }

	//! \~english Returns port
	//! \~russian Возвращает порт
	ushort port() const { return port_; }

	//! \~english Returns string IP
	//! \~russian Возвращает IP-адрес в виде строки
	PIString ipString() const;

	//! \~english Returns string representation of IP and port "i.i.i.i:p"
	//! \~russian Возвращает представление адреса в виде строки "i.i.i.i:p"
	PIString toString() const;

	//! \~english Set address IP
	//! \~russian Устанавливает IP-адрес
	void setIP(uint ip);

	//! \~english Set address IP
	//! \~russian Устанавливает IP-адрес
	void setIP(const PIString & ip);

	//! \~english Set address port
	//! \~russian Устанавливает порт
	void setPort(ushort port);

	//! \~english Set address IP and port, "i.i.i.i:p"
	//! \~russian Устанавливает IP-адрес и порт в виде строки "i.i.i.i:p"
	void set(const PIString & ip_port);

	//! \~english Set address IP and port, "i.i.i.i"
	//! \~russian Устанавливает IP-адрес в виде строки "i.i.i.i" и порт
	void set(const PIString & ip, ushort port);

	//! \~english Set address binary IP and port
	//! \~russian Устанавливает IP-адрес и порт в бинарном виде
	void set(uint ip, ushort port);

	//! \~english Set IP and port to 0
	//! \~russian Устанавливает IP-адрес и порт равными 0
	void clear();

	//! \~english Returns if IP and port is 0
	//! \~russian Возвращает true, если IP-адрес равен 0 и порт равен 0
	bool isNull() const;

	//! \~english Resolve hostname "host:port" and return it address or null address on error
	//! \~russian Получает IP-адрес и порт по имени хоста "host:port" и возвращает объект адреса, если получить удалось, иначе - null
	static PINetworkAddress resolve(const PIString & host_port);

	//! \~english Resolve hostname "host" with port "port" and return it address or null address on error
	//! \~russian Получает IP-адрес и порт по имени хоста "host" и порту "port" и возвращает объект адреса, если получить удалось, иначе -
	//! null
	static PINetworkAddress resolve(const PIString & host, ushort port);

	//! \~english Splits IP and port from string "i.i.i.i:p" to separate strings
	//! \~russian Разделяет IP-адрес и порт на отдельные строки
	static void splitIPPort(const PIString & ipp, PIString * _ip, int * _port);

private:
	void initIP(const PIString & _ip);

	union {
		uint ip_;
		uchar ip_b[4];
	};
	ushort port_;
};


inline bool operator==(const PINetworkAddress & v0, const PINetworkAddress & v1) {
	return (v0.ip() == v1.ip() && v0.port() == v1.port());
}
inline bool operator!=(const PINetworkAddress & v0, const PINetworkAddress & v1) {
	return (v0.ip() != v1.ip() || v0.port() != v1.port());
}


//! \relatesalso PICout
//! \~english \brief Output operator to PICout
//! \~russian \brief Оператор вывода в PICout
inline PICout operator<<(PICout s, const PINetworkAddress & v) {
	s.space();
	s.saveAndSetControls(0);
	s << "Address(" << v.toString() << ")";
	s.restoreControls();
	return s;
}


#endif // PINETWORKADDRESS_H
