/*
    Copyright 2005-2007 Adobe Systems Incorporated
    Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
    or a copy at http://stlab.adobe.com/licenses.html)
*/

/****************************************************************************************************/

#ifndef ADOBE_NUMBER_FORMATTER_HPP
#define ADOBE_NUMBER_FORMATTER_HPP

/****************************************************************************************************/

#include <GG/adobe/config.hpp>

#include <GG/adobe/future/platform_number_formatter_data.hpp>

#include <boost/bind.hpp>

#include <GG/adobe/future/locale.hpp>

#include <string>

// 1310 == VC++ 7.1
#if defined(_MSC_VER) && _MSC_VER <= 1310
    #include <sstream>
#endif

/****************************************************************************************************/

namespace adobe {

/****************************************************************************************************/

struct number_formatter_t
{
    number_formatter_t()
    {
        // NOTE (fbrereto) : MSVC 8 doesn't allow "this" to be used
        //                   in a constructor initializer, so we
        //                   assign it here.

        connection_m = adobe::monitor_locale(boost::bind(&number_formatter_t::monitor_locale,
                                                         boost::ref(*this),
                                                         _1));
    }

    ~number_formatter_t()
    {
        connection_m.disconnect();
    }

    void        set_format(const std::string& format);
    std::string get_format() const;

// 1310 == VC++ 7.1
#if defined(_MSC_VER) && _MSC_VER <= 1310
    // These workarounds are in place because of
    // an internal compiler error generated by
    // this code in MSVC 7.1.

    template <typename Numeric>
    std::string format(const Numeric& x)
    {
        std::stringstream result;
        result << x;
        return result.str();
    }

    template <typename Numeric>
    Numeric parse(const std::string& str, any_regular_t = any_regular_t())
    {
        return static_cast<Numeric>(std::atof(str.c_str()));
    }
#else
    template <typename Numeric>
    std::string format(const Numeric& x)
    { return format<any_regular_t>(any_regular_t(x)); }

    template <typename Numeric>
    Numeric parse(const std::string& str, any_regular_t = any_regular_t())
    { return parse<any_regular_t>(str, any_regular_t(Numeric())).template cast<Numeric>(); }
#endif

private:
    void monitor_locale(const dictionary_t&);

    number_formatter_platform_data_t data_m;
    boost::signals::connection       connection_m;
};

/****************************************************************************************************/

template <>
std::string number_formatter_t::format<any_regular_t>(const any_regular_t& x);

template <>
any_regular_t number_formatter_t::parse<any_regular_t>(const std::string& str, any_regular_t dummy);

/****************************************************************************************************/

bool completely_valid_number_string_given_current_locale(const std::string& value);

/****************************************************************************************************/

} // namespace adobe

/****************************************************************************************************/

// ADOBE_NUMBER_FORMATTER_HPP
#endif

/****************************************************************************************************/
