//
// Copyright (c) ZeroC, Inc. All rights reserved.
//

#ifndef ICE_UTIL_CONSOLE_UTIL_H
#define ICE_UTIL_CONSOLE_UTIL_H

#include <IceUtil/Config.h>
#include <IceUtil/StringConverter.h>
#include <iostream>

namespace IceUtilInternal
{

#if defined(_WIN32) && !defined(ICE_OS_UWP)

class ConsoleUtil;
ICE_DEFINE_PTR(ConsoleUtilPtr, ConsoleUtil);

class ICE_API ConsoleUtil
#  ifndef ICE_CPP11_MAPPING
    : public IceUtil::Shared
#  endif
{
public:

    ConsoleUtil();
    void output(const std::string&) const;
    void error(const std::string&) const;

private:

    std::string toConsoleEncoding(const std::string&) const;
    IceUtil::StringConverterPtr _converter;
    IceUtil::StringConverterPtr _consoleConverter;
};

const ICE_API ConsoleUtil& getConsoleUtil();

class ICE_API ConsoleOut
{
public:

    ConsoleOut& operator<<(ConsoleOut& (*pf)(ConsoleOut&));
};

class ICE_API ConsoleErr
{
public:

    ConsoleErr& operator<<(ConsoleErr& (*pf)(ConsoleErr&));
};

template<typename T>
ConsoleOut&
operator<<(ConsoleOut& out, const T& val)
{
    std::ostringstream s;
    s << val;
    getConsoleUtil().output(s.str());
    return out;
}

ICE_API ConsoleOut& endl(ConsoleOut&);
ICE_API ConsoleOut& flush(ConsoleOut&);

template<typename T>
ConsoleErr&
operator<<(ConsoleErr& err, const T& val)
{
    std::ostringstream s;
    s << val;
    getConsoleUtil().error(s.str());
    return err;
}

ICE_API ConsoleErr& endl(ConsoleErr&);
ICE_API ConsoleErr& flush(ConsoleErr&);

extern ICE_API ConsoleOut consoleOut ICE_GLOBAL_VAR_SUFFIX;
extern ICE_API ConsoleErr consoleErr ICE_GLOBAL_VAR_SUFFIX;

#else

extern ICE_API std::ostream& consoleOut ICE_GLOBAL_VAR_SUFFIX;
extern ICE_API std::ostream& consoleErr ICE_GLOBAL_VAR_SUFFIX;

#endif

}

#endif
