/**
 * Copyright (C) 2014 David Wolf <d.wolf@live.at>
 *
 * This file is part of Lupus.
 * Lupus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Lupus 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Lupus. If not, see <http://www.gnu.org/licenses/>.
 */
#pragma once

#include "String.h"
#include <cstdint>

namespace Lupus {
	//! Basis für die Ganzzahlkonversion.
	enum class IntegerBase {
		Octal,
		Decimal,
		Hexadecimal
	};

	//! Klasse für Ganzzahl konversionen.
    class LUPUSCORE_API Integer
	{
	public:
		//! \sa Integer::ToString(int, IntegerBase)
		static String ToString(int8_t value, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::ToString(int, IntegerBase)
        static String ToString(short value, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		/**
		 * Konvertiert eine Ganzzahl zu ihrer entsprechenden Zeichenkette.
		 *
		 * \param[in] value Ganzzahl für die Konvertierung
		 * \param[in] base Basis der Ganzzahl (8, 10, 16)
		 * \returns Entsprechende Zeichenkette der Ganzzahl
		 */
        static String ToString(int value, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::ToString(int, IntegerBase)
        static String ToString(long value, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::ToString(int, IntegerBase)
        static String ToString(long long value, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::ToString(int, IntegerBase)
        static String ToString(uint8_t value, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::ToString(int, IntegerBase)
        static String ToString(unsigned short value, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::ToString(int, IntegerBase)
        static String ToString(unsigned int value, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::ToString(int, IntegerBase)
        static String ToString(unsigned long value, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::ToString(int, IntegerBase)
        static String ToString(unsigned long long value, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::TryParse(const String&, int, IntegerBase)
        static bool TryParse(const String& string, int8_t& result, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::TryParse(const String&, int, IntegerBase)
        static bool TryParse(const String& string, short& result, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		/**
		 * Versucht eine Zeichenkette zu ihrer entsprechenden Ganzzahl zu 
		 * konvertieren.
		 *
		 * \param[in] String Zeichenkette die konvertiert werden soll.
		 * \param[out] result Variable in der das Ergebnis gespeichert wird.
		 * \param[in] base Basis der Ganzzahl (8, 10, 16)
		 * \returns TRUE wenn die Konvertierung erfolgreich war. 
         *          FALSE im Fehlerfall.
		 */
        static bool TryParse(const String& string, int& result, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::TryParse(const String&, int, IntegerBase)
        static bool TryParse(const String& string, long& result, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::TryParse(const String&, int, IntegerBase)
        static bool TryParse(const String& string, long long& result, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::TryParse(const String&, int, IntegerBase)
        static bool TryParse(const String& string, uint8_t& result, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::TryParse(const String&, int, IntegerBase)
        static bool TryParse(const String& string, unsigned short& result, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::TryParse(const String&, int, IntegerBase)
        static bool TryParse(const String& string, unsigned int& result, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::TryParse(const String&, int, IntegerBase)
        static bool TryParse(const String& string, unsigned long& result, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;
		//! \sa Integer::TryParse(const String&, int, IntegerBase)
        static bool TryParse(const String& string, unsigned long long& result, IntegerBase base = IntegerBase::Decimal) NOEXCEPT;

        static int8_t ParseByte(const String& string, IntegerBase base = IntegerBase::Decimal) throw(std::invalid_argument);
        static short ParseShort(const String& string, IntegerBase base = IntegerBase::Decimal) throw(std::invalid_argument);
        static int ParseInt(const String& string, IntegerBase base = IntegerBase::Decimal) throw(std::invalid_argument);
        static long ParseLong(const String& string, IntegerBase base = IntegerBase::Decimal) throw(std::invalid_argument);
        static long long ParseLongLong(const String& string, IntegerBase base = IntegerBase::Decimal) throw(std::invalid_argument);

        static uint8_t ParseUByte(const String& string, IntegerBase base = IntegerBase::Decimal) throw(std::invalid_argument);
        static unsigned short ParseUShort(const String& string, IntegerBase base = IntegerBase::Decimal) throw(std::invalid_argument);
        static unsigned int ParseUInt(const String& string, IntegerBase base = IntegerBase::Decimal) throw(std::invalid_argument);
        static unsigned long ParseULong(const String& string, IntegerBase base = IntegerBase::Decimal) throw(std::invalid_argument);
        static unsigned long long ParseULongLong(const String& string, IntegerBase base = IntegerBase::Decimal) throw(std::invalid_argument);
	};
}
