/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator
  Module:    $RCSfile: cmCommandArgumentsHelper.cxx,v $
  Language:  C++
  Date:      $Date: 2012/03/29 17:21:08 $
  Version:   $Revision: 1.1.1.1 $

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "cmCommandArgumentsHelper.h"

cmCommandArgument::cmCommandArgument(cmCommandArgumentsHelper* args, 
                                     const char* key, 
                                     cmCommandArgumentGroup* group)
:Key(key)
,Group(group)
,WasActive(false)
,ArgumentsBeforeEmpty(true)
,CurrentIndex(0) 
{
  if (args!=0)
    {
    args->AddArgument(this);
    }
    
  if (this->Group!=0)
    {
    this->Group->ContainedArguments.push_back(this);
    }
}

void cmCommandArgument::Reset()
{
  this->WasActive =false;
  this->CurrentIndex = 0;
  this->DoReset();
}

void cmCommandArgument::Follows(const cmCommandArgument* arg)
{
  this->ArgumentsBeforeEmpty = false;
  this->ArgumentsBefore.insert(arg);
}

void cmCommandArgument::FollowsGroup(const cmCommandArgumentGroup* group)
{
  if (group!=0)
    {
    this->ArgumentsBeforeEmpty = false;
    for(std::vector<cmCommandArgument*>::const_iterator 
        argIt= group->ContainedArguments.begin();
        argIt != group->ContainedArguments.end();
        ++argIt)
      {
      this->ArgumentsBefore.insert(*argIt);
      }
    }
}

bool cmCommandArgument::MayFollow(const cmCommandArgument* current) const
{
  if (this->ArgumentsBeforeEmpty)
    {
    return true;
    }

  std::set<const cmCommandArgument*>::const_iterator argIt 
                                         = this->ArgumentsBefore.find(current);
  if (argIt != this->ArgumentsBefore.end())
    {
    return true;
    }

  return false;
}

bool cmCommandArgument::KeyMatches(const std::string& key) const
{
  if ((this->Key==0) || (this->Key[0]=='\0'))
    {
    return true;
    }
  return (key==this->Key);
}

void cmCommandArgument::ApplyOwnGroup()
{
  if (this->Group!=0)
    {
    for (std::vector<cmCommandArgument*>::const_iterator 
         it = this->Group->ContainedArguments.begin();
         it != this->Group->ContainedArguments.end();
         ++it)
      {
      if(*it != this)
        {
        this->ArgumentsBefore.insert(*it);
        }
      }
    }
}

void cmCommandArgument::Activate()
{
  this->WasActive = true; 
  this->CurrentIndex = 0;
}

bool cmCommandArgument::Consume(const std::string& arg)
{
  bool res=this->DoConsume(arg, this->CurrentIndex);
  this->CurrentIndex++;
  return res;
}


cmCAStringVector::cmCAStringVector(cmCommandArgumentsHelper* args, 
                                   const char* key, 
                                   cmCommandArgumentGroup* group)
:cmCommandArgument(args, key, group)
,Ignore(0)
{
  if ((key==0) || (*key==0))
    {
    this->DataStart = 0;
    }
  else
    {
    this->DataStart = 1;
    }
}

bool cmCAStringVector::DoConsume(const std::string& arg,unsigned int index)
{
  if (index >= this->DataStart)
    {
    if ((this->Ignore==0) || (arg != this->Ignore))
      {
      this->Vector.push_back(arg);
      }
    }

  return false;
}

void cmCAStringVector::DoReset()
{
  this->Vector.clear();
}

cmCAString::cmCAString(cmCommandArgumentsHelper* args, 
                       const char* key, 
                       cmCommandArgumentGroup* group)
:cmCommandArgument(args, key, group)
{
  if ((key==0) || (*key==0))
    {
    this->DataStart = 0;
    }
  else
    {
    this->DataStart = 1;
    }
}

bool cmCAString::DoConsume(const std::string& arg, unsigned int index)
{
  if (index == this->DataStart)
    {
    this->String = arg;
    }

  return index >= this->DataStart;
}

void cmCAString::DoReset()
{
  this->String = this->DefaultString;
}

cmCAEnabler::cmCAEnabler(cmCommandArgumentsHelper* args, 
                         const char* key, 
                         cmCommandArgumentGroup* group)
:cmCommandArgument(args, key, group)
,Enabled(false) 
{}

bool cmCAEnabler::DoConsume(const std::string&, unsigned int index)
{
  if (index==0)
    {
    this->Enabled = true;
    }
  return true;
}

void cmCAEnabler::DoReset()
{
  this->Enabled = false;
}

cmCADisabler::cmCADisabler(cmCommandArgumentsHelper* args, 
                           const char* key, 
                           cmCommandArgumentGroup* group)
:cmCommandArgument(args, key, group)
,Enabled(true) 
{}

bool cmCADisabler::DoConsume(const std::string&, unsigned int index)
{
  if (index==0)
    {
    this->Enabled = false;
    }
  return true;
}

void cmCADisabler::DoReset()
{
  this->Enabled = true;
}

void cmCommandArgumentGroup::Follows(const cmCommandArgument* arg)
{
  for(std::vector<cmCommandArgument*>::iterator 
      it = this->ContainedArguments.begin();
      it != this->ContainedArguments.end();
      ++it)
    {
    (*it)->Follows(arg);
    }
}

void cmCommandArgumentGroup::FollowsGroup(const cmCommandArgumentGroup* group)
{
  for(std::vector<cmCommandArgument*>::iterator 
      it = this->ContainedArguments.begin();
      it != this->ContainedArguments.end();
      ++it)
    {
    (*it)->FollowsGroup(group);
    }
}

void cmCommandArgumentsHelper::Parse(const std::vector<std::string>* args, 
                                     std::vector<std::string>* unconsumedArgs)
{
  if(args==0)
    {
    return;
    }

  for(std::vector<cmCommandArgument*>::iterator 
      argIt = this->Arguments.begin();
      argIt != this->Arguments.end();
      ++argIt)
    {
    (*argIt)->ApplyOwnGroup();
    (*argIt)->Reset();
    }

  cmCommandArgument* activeArgument = 0;
  const cmCommandArgument* previousArgument = 0;
  for(std::vector<std::string>::const_iterator it = args->begin();
      it != args->end();
      ++it)
    {
    for(std::vector<cmCommandArgument*>::iterator 
        argIt = this->Arguments.begin();
        argIt != this->Arguments.end();
        ++argIt)
      {
      if ((*argIt)->KeyMatches(*it) && ((*argIt)->MayFollow(previousArgument)))
        {
        activeArgument = *argIt;
        activeArgument->Activate();
        break;
        }
      }

    if (activeArgument)
      {
      bool argDone = activeArgument->Consume(*it);
      previousArgument = activeArgument;
      if (argDone)
        {
        activeArgument = 0;
        }
      }
    else
      {
      if (unconsumedArgs!=0)
        {
        unconsumedArgs->push_back(*it);
        }
      }
    }
}

void cmCommandArgumentsHelper::AddArgument(cmCommandArgument* arg)
{
  this->Arguments.push_back(arg);
}

