// Copyright Vladimir Prus 2002-2004.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)


#include <boost/config.hpp>

#define BOOST_PROGRAM_OPTIONS_SOURCE
#include <boost/program_options/config.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/positional_options.hpp>
#include <boost/program_options/detail/cmdline.hpp>
#include <boost/program_options/detail/config_file.hpp>
#include <boost/program_options/environment_iterator.hpp>
#include <boost/program_options/detail/convert.hpp>

#include <boost/bind.hpp>
#include <boost/throw_exception.hpp>

#include <cctype>
#include <fstream>

#if !defined(__GNUC__) || __GNUC__ < 3
#include <iostream>
#else
#include <istream>
#endif

#ifdef _WIN32
#include <stdlib.h>
#else
#include <unistd.h>
#endif

// The 'environ' should be declared in some cases. E.g. Linux man page says:
// (This variable must be declared in the user program, but is declared in 
// the header file unistd.h in case the header files came from libc4 or libc5, 
// and in case they came from glibc and _GNU_SOURCE was defined.) 
// To be safe, declare it here.

// It appears that on Mac OS X the 'environ' variable is not
// available to dynamically linked libraries.
// See: http://article.gmane.org/gmane.comp.lib.boost.devel/103843
// See: http://lists.gnu.org/archive/html/bug-guile/2004-01/msg00013.html
#if defined(__APPLE__) && defined(__DYNAMIC__)
#include <crt_externs.h>
#define environ (*_NSGetEnviron()) 
#else
#if defined(__MWERKS__)
#include <crtl.h>
#else
#if !defined(_WIN32) || defined(__COMO_VERSION__)
extern char** environ;
#endif
#endif
#endif

using namespace std;

namespace boost { namespace program_options {

#ifndef BOOST_NO_STD_WSTRING
    namespace {
        woption woption_from_option(const option& opt)
        {
            woption result;
            result.string_key = opt.string_key;
            result.position_key = opt.position_key;
            result.unregistered = opt.unregistered;
            
            std::transform(opt.value.begin(), opt.value.end(),
                           back_inserter(result.value),
                           boost::bind(from_utf8, _1));

            std::transform(opt.original_tokens.begin(), 
                           opt.original_tokens.end(),
                           back_inserter(result.original_tokens),
                           boost::bind(from_utf8, _1));
            return result;
        }
    }

    basic_parsed_options<wchar_t>
    ::basic_parsed_options(const parsed_options& po)
    : description(po.description),
      utf8_encoded_options(po)
    {
        for (unsigned i = 0; i < po.options.size(); ++i)
            options.push_back(woption_from_option(po.options[i]));
    }
#endif

    template<class charT>
    basic_parsed_options<charT>
    parse_config_file(std::basic_istream<charT>& is, 
                      const options_description& desc,
                      bool allow_unregistered)
    {    
        set<string> allowed_options;

        const vector<shared_ptr<option_description> >& options = desc.options();
        for (unsigned i = 0; i < options.size(); ++i)
        {
            const option_description& d = *options[i];

            if (d.long_name().empty())
                boost::throw_exception(
                    error("long name required for config file"));

            allowed_options.insert(d.long_name());
        }

        // Parser return char strings
        parsed_options result(&desc);        
        copy(detail::basic_config_file_iterator<charT>(
                 is, allowed_options, allow_unregistered), 
             detail::basic_config_file_iterator<charT>(), 
             back_inserter(result.options));
        // Convert char strings into desired type.
        return basic_parsed_options<charT>(result);
    }

    template
    BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char>
    parse_config_file(std::basic_istream<char>& is, 
                      const options_description& desc,
                      bool allow_unregistered);

#ifndef BOOST_NO_STD_WSTRING
    template
    BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t>
    parse_config_file(std::basic_istream<wchar_t>& is, 
                      const options_description& desc,
                      bool allow_unregistered);
#endif

    template<class charT>
    basic_parsed_options<charT>
    parse_config_file(const char* filename, 
                      const options_description& desc,
                      bool allow_unregistered)
    { 
        // Parser return char strings
        std::basic_ifstream< charT > strm(filename);
        if (!strm) 
        {
            boost::throw_exception(reading_file(filename));
        }
        return parse_config_file(strm, desc, allow_unregistered);
    }

    template
    BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char>
    parse_config_file(const char* filename, 
                      const options_description& desc,
                      bool allow_unregistered);

#ifndef BOOST_NO_STD_WSTRING
    template
    BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t>
    parse_config_file(const char* filename, 
                      const options_description& desc,
                      bool allow_unregistered);
#endif

    
// This versio, which accepts any options without validation, is disabled,
// in the hope that nobody will need it and we cant drop it altogether.
// Besides, probably the right way to handle all options is the '*' name.
#if 0
    BOOST_PROGRAM_OPTIONS_DECL parsed_options
    parse_config_file(std::istream& is)
    {
        detail::config_file_iterator cf(is, false);
        parsed_options result(0);
        copy(cf, detail::config_file_iterator(), 
             back_inserter(result.options));
        return result;
    }
#endif

    BOOST_PROGRAM_OPTIONS_DECL parsed_options
    parse_environment(const options_description& desc, 
                      const function1<std::string, std::string>& name_mapper)
    {
        parsed_options result(&desc);
        
        for(environment_iterator i(environ), e; i != e; ++i) {
            string option_name = name_mapper(i->first);

            if (!option_name.empty()) {
                option n;
                n.string_key = option_name;
                n.value.push_back(i->second);
                result.options.push_back(n);
            }                
        }

        return result;
    }

    namespace detail {
        class prefix_name_mapper {
        public:
            prefix_name_mapper(const std::string& prefix)
            : prefix(prefix)
            {}

            std::string operator()(const std::string& s)
            {
                string result;
                if (s.find(prefix) == 0) {
                    for(string::size_type n = prefix.size(); n < s.size(); ++n) 
                    {   
                        // Intel-Win-7.1 does not understand
            // push_back on string.         
                        result += tolower(s[n]);
                    }
                }
                return result;
            }
        private:
            std::string prefix;
        };
    }

    BOOST_PROGRAM_OPTIONS_DECL parsed_options
    parse_environment(const options_description& desc, 
                      const std::string& prefix)
    {
        return parse_environment(desc, detail::prefix_name_mapper(prefix));
    }

    BOOST_PROGRAM_OPTIONS_DECL parsed_options
    parse_environment(const options_description& desc, const char* prefix)
    {
        return parse_environment(desc, string(prefix));
    }




}}
