/* -*- mia-c++  -*-
 *
 * This file is part of MIA - a toolbox for medical image analysis
 * Copyright (c) Leipzig, Madrid 1999-2017 Gert Wollny
 *
 * MIA 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.
 *
 * This program 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 MIA; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <stdexcept>
#include <sstream>
#include <algorithm>

#include <mia/core/optparam.hh>
#include <mia/core/tools.hh>
#include <mia/core/xmlinterface.hh>

NS_MIA_BEGIN

using namespace std;



bool CParamList::has_key(const std::string& key) const
{
       return m_params.find(key) != m_params.end();
}

CParamList::PParameter& CParamList::operator [] (const std::string& key)
{
       return m_params[key];
}

void CParamList::set(const CParsedOptions& options)
{
       typedef std::map<std::string, PParameter>::iterator::value_type MapValue;
       for_each(m_params.begin(), m_params.end(), [](MapValue p) {
              p.second->reset();
       });

       for (auto i = options.begin();
            i != options.end(); ++i) {
              auto p = m_params.find(i->first);

              if (p == m_params.end()) {
                     stringstream msg;
                     msg << "unknown parameter '" << i->first << "'";
                     throw invalid_argument(msg.str());
              }

              if (!p->second->set(i->second))  {
                     stringstream msg;
                     msg << "Parameter '" << i->first << "' unable to interpret '" << i->second;
                     throw invalid_argument(msg.str());
              }
       }

       for_each(m_params.begin(), m_params.end(), [](MapValue p) {
              p.second->post_set();
       });
}

void CParamList::check_required() const
{
       for (auto i = m_params.begin(); i != m_params.end(); ++i) {
              if (i->second->required_set()) {
                     stringstream msg;
                     msg << "parameter '" << i->first << "' required ";
                     throw invalid_argument(msg.str());
              }
       }
}

void CParamList::print_help(std::ostream& os) const
{
       auto  i = m_params.begin();

       while ( i != m_params.end() ) {
              os  << "\n\t" << i->first;
              i->second->value(os);
              os << "\n\t\t";
              i->second->descr(os);
              ++i;
       }

       os << "\n";
}

void CParamList::get_help_xml(CXMLElement& root)const
{
       TRACE_FUNCTION;

       for ( auto i = m_params.begin(); i != m_params.end(); ++i ) {
              cvdebug() << "   param '" << i->first << "'\n";
              auto p = root.add_child("param");
              p->set_attribute("name", i->first);
              i->second->get_help_xml(*p);
       }
}

void CParamList::add_dependend_handlers(HandlerHelpMap& handler_map) const
{
       TRACE_FUNCTION;

       for (auto p = m_params.begin(); p != m_params.end(); ++p)
              p->second->add_dependend_handler(handler_map);
}

NS_MIA_END
