/*============================================================================
  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;
}
