/*
 * Project: MoleCuilder
 * Description: creates and alters molecular systems
 * Copyright (C)  2010-2012 University of Bonn. All rights reserved.
 * 
 *
 *   This file is part of MoleCuilder.
 *
 *    MoleCuilder 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 2 of the License, or
 *    (at your option) any later version.
 *
 *    MoleCuilder 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 MoleCuilder.  If not, see .
 */
/*
 * CommandLineParser_validate.cpp
 *
 *  Created on: Nov 8, 2010
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
//#include "CodePatterns/MemDebug.hpp"
#include 
#include 
#include 
#include "Actions/Values.hpp"
#include "CommandLineParser_validate.hpp"
#include "Parameters/Specifics/KeyValuePair.hpp"
/** boost::program_options validator specialization for VectorValue.
 * \param &v  reference for return value
 * \param &values string vector of scanned options
 * \param *
 * \param
 *
 */
void validate(boost::any& v, const std::vector& values, VectorValue *, int)
{
  VectorValue VV;
  std::vector components;
  // split comma-separated values
  if (values.size() != 1) {
    std::cerr <<  "Not one vector but " << values.size() << " given " << std::endl;
#if BOOST_VERSION < 104200
    throw boost::program_options::validation_error("Unequal to one vector given");
#else
    throw boost::program_options::validation_error(
        boost::program_options::validation_error::invalid_option_value,
        std::string("value"),
        std::string("VectorValue")
    );
#endif
  }
  std::string argument(values.at(0));
  std::string::iterator Aiter = argument.begin();
  std::string::iterator Biter = argument.begin();
  for (; Aiter != argument.end(); ++Aiter) {
    if (*Aiter == ',') {
      components.push_back(std::string(Biter,Aiter));
      do {
        Aiter++;
      } while (*Aiter == ' ' || *Aiter == '\t');
      Biter = Aiter;
    }
  }
  components.push_back(std::string(Biter,argument.end()));
  if (components.size() != 3) {
    std::cerr <<  "Specified vector does not have three components but " << components.size() << std::endl;
#if BOOST_VERSION < 104200
    throw boost::program_options::validation_error("Specified vector does not have three components");
#else
    throw boost::program_options::validation_error(
        boost::program_options::validation_error::invalid_option_value,
        std::string("value"),
        std::string("VectorValue")
    );
#endif
  }
  for (size_t i=0;i(components.at(i));
  v = boost::any(VectorValue(VV));
}
void validate(boost::any& v, const std::vector& values, RealSpaceMatrixValue *, int)
{
  RealSpaceMatrixValue RSMV;
  std::vector components;
  // split comma-separated values
  if (values.size() != 1) {
    std::cerr <<  "Not one vector but " << values.size() << " given " << std::endl;
#if BOOST_VERSION < 104200
    throw boost::program_options::validation_error("Unequal to one vector given");
#else
    throw boost::program_options::validation_error(
        boost::program_options::validation_error::invalid_option_value,
        std::string("value"),
        std::string("BoxValue")
    );
#endif
  }
  std::string argument(values.at(0));
  std::string::iterator Aiter = argument.begin();
  std::string::iterator Biter = argument.begin();
  for (; Aiter != argument.end(); ++Aiter) {
    if (*Aiter == ',') {
      components.push_back(std::string(Biter,Aiter));
      do {
        Aiter++;
      } while (*Aiter == ' ' || *Aiter == '\t');
      Biter = Aiter;
    }
  }
  components.push_back(std::string(Biter,argument.end()));
  if (components.size() != 6) {
    std::cerr <<  "Specified vector does not have three components but " << components.size() << std::endl;
#if BOOST_VERSION < 104200
    throw boost::program_options::validation_error("Specified symmetric box matrix does not have six components");
#else
    throw boost::program_options::validation_error(
        boost::program_options::validation_error::invalid_option_value,
        std::string("value"),
        std::string("BoxValue")
    );
#endif
  }
  for (size_t i=0;i<(NDIM*(NDIM+1))/2; ++i)
    RSMV.matrix[i] = boost::lexical_cast(components.at(i));
  v = boost::any(RealSpaceMatrixValue(RSMV));
}
/** boost::program_options validator specialization for boost::filesystem::path.
 * \param &v  reference for return value
 * \param &values string vector of scanned options
 * \param *
 * \param
 *
 */
void validate(boost::any& v, const std::vector& values, boost::filesystem::path *, int)
{
//  std::cerr << "boost::filesystem::path validator used." << std::endl;
  // Make sure no previous assignment to 'a' was made.
  boost::program_options::validators::check_first_occurrence(v);
  // Extract the first string from 'values'. If there is more than
  // one string, it's an error, and exception will be thrown.
  const std::string& s = boost::program_options::validators::get_single_string(values);
  v = boost::any(boost::filesystem::path(s));
}
/** boost::program_options validator specialization for boost::filesystem::path.
 * \param &v  reference for return value
 * \param &values string vector of scanned options
 * \param *
 * \param
 *
 */
void validate(boost::any& v, const std::vector& values, KeyValuePair *, int)
{
//  std::cerr << "KeyValuePair validator used." << std::endl;
  // Make sure no previous assignment to 'a' was made.
  boost::program_options::validators::check_first_occurrence(v);
  // Extract the first string from 'values'. If there is more than
  // one string, it's an error, and exception will be thrown.
  const std::string& s = boost::program_options::validators::get_single_string(values);
  if (s.find("=") == std::string::npos) {
#if BOOST_VERSION < 104200
    throw boost::program_options::validation_error("Invalid KeyValue given");
#else
throw boost::program_options::validation_error(
    boost::program_options::validation_error::invalid_option_value,
    std::string("value"),
    std::string("vector")
    );
#endif
  }
  v = boost::any(KeyValuePair(s));
}
/** boost::program_options validator specialization for boost::filesystem::path.
 * \param &v  reference for return value
 * \param &values string vector of scanned options
 * \param *
 * \param
 *
 */
void validate(boost::any& v, const std::vector& values, std::vector *, int)
{
//  std::cerr << "vector validator used." << std::endl;
  // split comma-separated values
  if (values.size() > 1) {
#if BOOST_VERSION < 104200
    throw boost::program_options::validation_error("Unequal to one file given");
#else
    if (values.size() == 0) {
      throw boost::program_options::validation_error(
          boost::program_options::validation_error::at_least_one_value_required,
          std::string("value"),
          std::string("vector")
      );
    }
#endif
    for (std::vector::const_iterator iter = values.begin();
        iter != values.end();++iter)
      if ((*iter).find("=") == std::string::npos) {
#if BOOST_VERSION < 104200
    throw boost::program_options::validation_error("Invalid KeyValue given");
#else
    throw boost::program_options::validation_error(
        boost::program_options::validation_error::invalid_option_value,
        std::string("value"),
        std::string("vector")
    );
#endif
      }
  }
  std::vector temp;
  for (std::vector::const_iterator iter = values.begin();
      iter != values.end();++iter)
    temp.push_back(KeyValuePair(*iter));
  v = boost::any(temp);
}