/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2015 Matthias Maennich <matthias@maennich.net>
  Copyright 2010 Alexander Neundorf <neundorf@kde.org>

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/

#include "cmParseArgumentsCommand.h"
#include "cmAlgorithms.h"

//----------------------------------------------------------------------------
bool cmParseArgumentsCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
{
  // cmake_parse_arguments(prefix options single multi <ARGN>)
  //                         1       2      3      4
  if (args.size() < 4)
    {
    this->SetError("must be called with at least 4 arguments.");
    return false;
    }

  std::vector<std::string>::const_iterator argIter = args.begin(),
                                           argEnd  = args.end();
  // the first argument is the prefix
  const std::string prefix = (*argIter++) + "_";

  // define the result maps holding key/value pairs for
  // options, single values and multi values
  typedef std::map<std::string, bool> options_map;
  typedef std::map<std::string, std::string> single_map;
  typedef std::map<std::string, std::vector<std::string> > multi_map;
  options_map options;
  single_map single;
  multi_map multi;

  // anything else is put into a vector of unparsed strings
  std::vector<std::string> unparsed;

  // remember already defined keywords
  std::set<std::string> used_keywords;
  const std::string dup_warning = "keyword defined more than once: ";

  // the second argument is a (cmake) list of options without argument
  std::vector<std::string> list;
  cmSystemTools::ExpandListArgument(*argIter++, list);
  for (std::vector<std::string>::const_iterator iter  = list.begin(),
                                                end   = list.end();
                                                iter != end; ++iter)
    {
    if (!used_keywords.insert(*iter).second)
      {
      this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
      }
    options[*iter]; // default initialize
    }

  // the third argument is a (cmake) list of single argument options
  list.clear();
  cmSystemTools::ExpandListArgument(*argIter++, list);
  for (std::vector<std::string>::const_iterator iter  = list.begin(),
                                                end   = list.end();
                                                iter != end; ++iter)
    {
    if (!used_keywords.insert(*iter).second)
      {
      this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
      }
    single[*iter]; // default initialize
    }

  // the fourth argument is a (cmake) list of multi argument options
  list.clear();
  cmSystemTools::ExpandListArgument(*argIter++, list);
  for (std::vector<std::string>::const_iterator iter  = list.begin(),
                                                end   = list.end();
                                                iter != end; ++iter)
    {
    if (!used_keywords.insert(*iter).second)
      {
      this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + *iter);
      }
    multi[*iter]; // default initialize
    }

  enum insideValues
  {
    NONE,
    SINGLE,
    MULTI
  } insideValues = NONE;
  std::string currentArgName;

  // Flatten ;-lists in the arguments into a single list as was done
  // by the original function(CMAKE_PARSE_ARGUMENTS).
  list.clear();
  for(; argIter != argEnd; ++argIter)
    {
    cmSystemTools::ExpandListArgument(*argIter, list);
    }

  // iterate over the arguments list and fill in the values where applicable
  for (argIter = list.begin(), argEnd = list.end();
       argIter != argEnd; ++argIter)
    {
    const options_map::iterator optIter = options.find(*argIter);
    if (optIter != options.end())
      {
      insideValues = NONE;
      optIter->second = true;
      continue;
      }

    const single_map::iterator singleIter = single.find(*argIter);
    if (singleIter != single.end())
      {
      insideValues = SINGLE;
      currentArgName = *argIter;
      continue;
      }

    const multi_map::iterator multiIter = multi.find(*argIter);
    if (multiIter != multi.end())
      {
      insideValues = MULTI;
      currentArgName = *argIter;
      continue;
      }

    switch(insideValues)
      {
      case SINGLE:
        single[currentArgName] = *argIter;
        insideValues = NONE;
        break;
      case MULTI:
        multi[currentArgName].push_back(*argIter);
        break;
      default:
        unparsed.push_back(*argIter);
        break;
      }
    }

  // now iterate over the collected values and update their definition
  // within the current scope. undefine if necessary.

  for (options_map::const_iterator iter = options.begin(), end = options.end();
                                   iter != end; ++iter)
    {
    this->Makefile->AddDefinition(prefix + iter->first,
                                  iter->second? "TRUE": "FALSE");
    }
  for (single_map::const_iterator iter = single.begin(), end = single.end();
                                  iter != end; ++iter)
    {
    if (!iter->second.empty())
      {
      this->Makefile->AddDefinition(prefix + iter->first,
                                    iter->second.c_str());
      }
    else
      {
      this->Makefile->RemoveDefinition(prefix + iter->first);
      }
    }

  for (multi_map::const_iterator iter = multi.begin(), end = multi.end();
                                  iter != end; ++iter)
    {
    if (!iter->second.empty())
      {
      this->Makefile->AddDefinition(prefix + iter->first,
                                    cmJoin(cmMakeRange(iter->second), ";")
                                      .c_str());
      }
    else
      {
      this->Makefile->RemoveDefinition(prefix + iter->first);
      }
    }

  if (!unparsed.empty())
    {
    this->Makefile->AddDefinition(prefix + "UNPARSED_ARGUMENTS",
                                  cmJoin(cmMakeRange(unparsed), ";").c_str());
    }
  else
    {
    this->Makefile->RemoveDefinition(prefix + "UNPARSED_ARGUMENTS");
    }

  return true;
}
