/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium

  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 "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);
}

