//! \~\file piunits_value.h
//! \~\ingroup Units
//! \~\brief
//! \~english Typed unit value
//! \~russian Типизированное значение единицы измерения
/*
    PIP - Platform Independent Primitives
    Unit value
    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 PIUNITS_VALUE_H
#define PIUNITS_VALUE_H

#include "piunits_base.h"


//! \~\ingroup Units
//! \~\brief
//! \~english Namespace containing typed unit values and helpers.
//! \~russian Пространство имен с типизированными значениями единиц и вспомогательными средствами.
namespace PIUnits {

//! \class PIUnits::Value
//! \~\ingroup Units
//! \~\brief
//! \~english Numeric value paired with a registered unit type.
//! \~russian Числовое значение, связанное с зарегистрированным типом единицы.
class PIP_EXPORT Value {
public:
	//! \~english Constructs value "v" of unit type "t".
	//! \~russian Создает значение "v" типа единицы "t".
	Value(double v = 0., int t = Class::Invalid);


	//! \~english Returns whether the value references a registered unit type.
	//! \~russian Возвращает, ссылается ли значение на зарегистрированный тип единицы.
	bool isValid() const { return m_type >= 0 && m_class; }

	//! \~english Returns whether the value has no registered unit type.
	//! \~russian Возвращает, не содержит ли значение зарегистрированного типа единицы.
	bool isNotValid() const { return m_type < 0 || !m_class; }


	//! \~english Returns stored numeric value.
	//! \~russian Возвращает сохраненное числовое значение.
	double value() const { return m_value; }

	//! \~english Formats the value with localized unit suffix and automatic prefix when supported.
	//! \~russian Форматирует значение с локализованным обозначением единицы и автоматическим префиксом, если он поддерживается.
	PIString toString(char format = 'g', int prec = 5) const;


	//! \~english Converts the value to unit type "type_to" inside the same unit family.
	//! \~russian Преобразует значение к типу единицы "type_to" внутри того же семейства единиц.
	bool convert(int type_to);

	//! \~english Returns converted copy in unit type "type_to", or invalid value on failure.
	//! \~russian Возвращает преобразованную копию в типе единицы "type_to" или невалидное значение при ошибке.
	Value converted(int type_to);

private:
	double m_value                       = 0.;
	int m_type                           = -1;
	Class::Internal::ClassBase * m_class = nullptr;
};

}; // namespace PIUnits

//! \~\ingroup Units
//! \relatesalso PIUnits::Value
//! \~english Writes formatted unit value to \a PICout.
//! \~russian Записывает форматированное значение единицы в \a PICout.
inline PICout operator<<(PICout s, const PIUnits::Value & v) {
	s << v.toString();
	return s;
}

#endif
