/** @file		NetF_Bytes.h
 *  @brief	Type safe data count calculations
 *  @author	netfinity
 */
#pragma once

#include "NetF_NoCast.h"
#include "OtherFunctions.h"

/**
 *  @brief	Container for bytes count
 */
class CBytes
{
public:
	CBytes(const sint64& qwBytes = 0);
	CBytes(const CBytes& bytes);
	// Conversions
	sint64 GetValue() const;
	CString ToString() const;
	// Assignments
	CBytes operator = (const CBytes& bytes);
	CBytes operator = (const sint64& bytes);
	CBytes operator += (const CBytes& bytes);
	CBytes operator -= (const CBytes& bytes);
	// Comparisations
	bool operator == (const CBytes& bytes) const;
	bool operator != (const CBytes& bytes) const;
	bool operator >= (const CBytes& bytes) const;
	bool operator <= (const CBytes& bytes) const;
	bool operator > (const CBytes& bytes) const;
	bool operator < (const CBytes& bytes) const;
	// Arithmetics
	CBytes operator - (void) const;
	CBytes operator + (const CBytes& bytes) const;
	CBytes operator - (const CBytes& bytes) const;
	CBytes operator * (const float& multiplier) const;
	CBytes operator / (const float& divisor) const;
	CBytes operator % (const CBytes& bytes) const;
	// Type casts
//	operator sint64() const;
	// Special arithmetics
//	int operator / (const CBytes& bytes) const;
//	float operator / (const CBytes& bytes) const;
private:
	sint64	m_qwBytes;
};

//
//	inline operations
//

inline
CBytes::CBytes(const sint64& qwBytes) : m_qwBytes(qwBytes)
{
}

inline
CBytes::CBytes(const CBytes& bytes) : m_qwBytes(bytes.m_qwBytes)
{
}

inline
sint64
CBytes::GetValue() const
{
	return m_qwBytes;
}

inline
CString
CBytes::ToString() const
{
	if (m_qwBytes >= 0)
		return ::CastItoXBytes((uint64) m_qwBytes, false, false, 2);
	else
		return _T("-") + ::CastItoXBytes((uint64) -m_qwBytes, false, false, 2);
}

inline
bool
CBytes::operator == (const CBytes& bytes) const
{
	return m_qwBytes == bytes.m_qwBytes;
}

inline
bool
CBytes::operator != (const CBytes& bytes) const
{
	return m_qwBytes != bytes.m_qwBytes;
}

inline
bool
CBytes::operator >= (const CBytes& bytes) const
{
	return m_qwBytes >= bytes.m_qwBytes;
}

inline
bool
CBytes::operator <= (const CBytes& bytes) const
{
	return m_qwBytes <= bytes.m_qwBytes;
}

inline
bool
CBytes::operator > (const CBytes& bytes) const
{
	return m_qwBytes > bytes.m_qwBytes;
}

inline
bool
CBytes::operator < (const CBytes& bytes) const
{
	return m_qwBytes < bytes.m_qwBytes;
}

inline
CBytes
CBytes::operator = (const CBytes& bytes)
{
	return m_qwBytes = bytes.m_qwBytes;
}

inline
CBytes
CBytes::operator = (const sint64& bytes)
{
	return m_qwBytes = bytes;
}

inline
CBytes
CBytes::operator += (const CBytes& bytes)
{
	return m_qwBytes += bytes.m_qwBytes;
}

inline
CBytes
CBytes::operator -= (const CBytes& bytes)
{
	return m_qwBytes -= bytes.m_qwBytes;
}

inline
CBytes
CBytes::operator - (void) const
{
	return CBytes(-m_qwBytes);
}

inline
CBytes
CBytes::operator + (const CBytes& bytes) const
{
	return CBytes(m_qwBytes + bytes.m_qwBytes);
}

inline
CBytes
CBytes::operator - (const CBytes& bytes) const
{
	return CBytes(m_qwBytes - bytes.m_qwBytes);
}

inline
CBytes
CBytes::operator * (const float& multiplier) const
{
	return CBytes(m_qwBytes * multiplier);
}

inline
CBytes
CBytes::operator / (const float& divisor) const
{
	return CBytes(m_qwBytes / divisor);
}

inline
CBytes
CBytes::operator % (const CBytes& bytes) const
{
	return CBytes(m_qwBytes % bytes.m_qwBytes);
}

//
//	Special arithmetics
//

inline
CBytes
operator * (const float& multiplier, const CBytes& bytes)
{
	return CBytes(multiplier * bytes.GetValue());
}

inline
float
operator / (const CBytes& bytes1, const CBytes& bytes2)
{
	return ((float) bytes1.GetValue() / (float) bytes2.GetValue());
}

/**
 *  @brief	Container for byte offsets
 */
/*class CByteOffset
{
public:
	CByteOffset(const sint64 qwOffset = 0);
	CByteOffset(const CByteOffset& offset);
	// Conversions
	sint64 GetValue() const;
	CString ToString() const;
	// Assignments
	CByteOffset operator = (const CByteOffset& offset);
	CByteOffset operator += (const CBytes& bytes);
	CByteOffset operator -= (const CBytes& bytes);
	// Comparisations
	bool operator == (const CByteOffset& offset) const;
	bool operator != (const CByteOffset& offset) const;
	bool operator >= (const CByteOffset& offset) const;
	bool operator <= (const CByteOffset& offset) const;
	bool operator > (const CByteOffset& offset) const;
	bool operator < (const CByteOffset& offset) const;
	// Arithmetics
	CByteOffset operator - (void) const;
	CByteOffset operator + (const CBytes& bytes) const;
	CByteOffset operator - (const CBytes& bytes) const;
	CByteOffset operator - (const CByteOffset& offset) const;
	float operator / (const CBytes& bytes) const;
	CByteOffset operator % (const CBytes& bytes) const;
	// Special arithmetics
//	int operator / (const CBytes& bytes) const;
//	float operator / (const CBytes& bytes) const;
private:
	sint64	m_qwOffset;
};*/

typedef CBytes	CByteOffset;
typedef CBytes	CByteCount;

//
//	
//

inline
CString
CastItoXBytes(const CBytes& bytes, uint32 decimal = 2)
{
	if (bytes >= 0)
		return ::CastItoXBytes((uint64) bytes.GetValue(), false, false, decimal);
	else
		return _T("-") + ::CastItoXBytes((uint64) (-bytes.GetValue()), false, false, decimal);
}

inline 
int 
CompareUnsigned(CBytes uSize1, CBytes uSize2)
{
	if (uSize1.GetValue() < uSize2.GetValue())
		return -1;
	if (uSize1.GetValue() > uSize2.GetValue())
		return 1;
	return 0;
}