/*============================================================================
  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 "cmSetPropertyCommand.h"

#include "cmSetSourceFilesPropertiesCommand.h"
#include "cmSetTargetPropertiesCommand.h"
#include "cmSetTestsPropertiesCommand.h"

cmSetPropertyCommand::cmSetPropertyCommand()
{
  this->AppendMode = false;
  this->AppendAsString = false;
  this->Remove = true;
}

bool cmSetPropertyCommand::InitialPass(std::vector<std::string> const& args,
                                       cmExecutionStatus&)
{
  if (args.size() < 2) {
    this->SetError("called with incorrect number of arguments");
    return false;
  }

  // Get the scope on which to set the property.
  std::vector<std::string>::const_iterator arg = args.begin();
  cmProperty::ScopeType scope;
  if (*arg == "GLOBAL") {
    scope = cmProperty::GLOBAL;
  } else if (*arg == "DIRECTORY") {
    scope = cmProperty::DIRECTORY;
  } else if (*arg == "TARGET") {
    scope = cmProperty::TARGET;
  } else if (*arg == "SOURCE") {
    scope = cmProperty::SOURCE_FILE;
  } else if (*arg == "TEST") {
    scope = cmProperty::TEST;
  } else if (*arg == "CACHE") {
    scope = cmProperty::CACHE;
  } else if (*arg == "INSTALL") {
    scope = cmProperty::INSTALL;
  } else {
    std::ostringstream e;
    e << "given invalid scope " << *arg << ".  "
      << "Valid scopes are GLOBAL, DIRECTORY, "
         "TARGET, SOURCE, TEST, CACHE, INSTALL.";
    this->SetError(e.str());
    return false;
  }

  // Parse the rest of the arguments up to the values.
  enum Doing
  {
    DoingNone,
    DoingNames,
    DoingProperty,
    DoingValues
  };
  Doing doing = DoingNames;
  const char* sep = "";
  for (++arg; arg != args.end(); ++arg) {
    if (*arg == "PROPERTY") {
      doing = DoingProperty;
    } else if (*arg == "APPEND") {
      doing = DoingNone;
      this->AppendMode = true;
      this->Remove = false;
      this->AppendAsString = false;
    } else if (*arg == "APPEND_STRING") {
      doing = DoingNone;
      this->AppendMode = true;
      this->Remove = false;
      this->AppendAsString = true;
    } else if (doing == DoingNames) {
      this->Names.insert(*arg);
    } else if (doing == DoingProperty) {
      this->PropertyName = *arg;
      doing = DoingValues;
    } else if (doing == DoingValues) {
      this->PropertyValue += sep;
      sep = ";";
      this->PropertyValue += *arg;
      this->Remove = false;
    } else {
      std::ostringstream e;
      e << "given invalid argument \"" << *arg << "\".";
      this->SetError(e.str());
      return false;
    }
  }

  // Make sure a property name was found.
  if (this->PropertyName.empty()) {
    this->SetError("not given a PROPERTY <name> argument.");
    return false;
  }

  // Dispatch property setting.
  switch (scope) {
    case cmProperty::GLOBAL:
      return this->HandleGlobalMode();
    case cmProperty::DIRECTORY:
      return this->HandleDirectoryMode();
    case cmProperty::TARGET:
      return this->HandleTargetMode();
    case cmProperty::SOURCE_FILE:
      return this->HandleSourceMode();
    case cmProperty::TEST:
      return this->HandleTestMode();
    case cmProperty::CACHE:
      return this->HandleCacheMode();
    case cmProperty::INSTALL:
      return this->HandleInstallMode();

    case cmProperty::VARIABLE:
    case cmProperty::CACHED_VARIABLE:
      break; // should never happen
  }
  return true;
}

bool cmSetPropertyCommand::HandleGlobalMode()
{
  if (!this->Names.empty()) {
    this->SetError("given names for GLOBAL scope.");
    return false;
  }

  // Set or append the property.
  cmake* cm = this->Makefile->GetCMakeInstance();
  const char* name = this->PropertyName.c_str();
  const char* value = this->PropertyValue.c_str();
  if (this->Remove) {
    value = 0;
  }
  if (this->AppendMode) {
    cm->AppendProperty(name, value ? value : "", this->AppendAsString);
  } else {
    cm->SetProperty(name, value);
  }

  return true;
}

bool cmSetPropertyCommand::HandleDirectoryMode()
{
  if (this->Names.size() > 1) {
    this->SetError("allows at most one name for DIRECTORY scope.");
    return false;
  }

  // Default to the current directory.
  cmMakefile* mf = this->Makefile;

  // Lookup the directory if given.
  if (!this->Names.empty()) {
    // Construct the directory name.  Interpret relative paths with
    // respect to the current directory.
    std::string dir = *this->Names.begin();
    if (!cmSystemTools::FileIsFullPath(dir.c_str())) {
      dir = this->Makefile->GetCurrentSourceDirectory();
      dir += "/";
      dir += *this->Names.begin();
    }

    // The local generators are associated with collapsed paths.
    dir = cmSystemTools::CollapseFullPath(dir);

    mf = this->Makefile->GetGlobalGenerator()->FindMakefile(dir);
    if (!mf) {
      // Could not find the directory.
      this->SetError(
        "DIRECTORY scope provided but requested directory was not found. "
        "This could be because the directory argument was invalid or, "
        "it is valid but has not been processed yet.");
      return false;
    }
  }

  // Set or append the property.
  const char* name = this->PropertyName.c_str();
  const char* value = this->PropertyValue.c_str();
  if (this->Remove) {
    value = 0;
  }
  if (this->AppendMode) {
    mf->AppendProperty(name, value ? value : "", this->AppendAsString);
  } else {
    mf->SetProperty(name, value);
  }

  return true;
}

bool cmSetPropertyCommand::HandleTargetMode()
{
  for (std::set<std::string>::const_iterator ni = this->Names.begin();
       ni != this->Names.end(); ++ni) {
    if (this->Makefile->IsAlias(*ni)) {
      this->SetError("can not be used on an ALIAS target.");
      return false;
    }
    if (cmTarget* target = this->Makefile->FindTargetToUse(*ni)) {
      // Handle the current target.
      if (!this->HandleTarget(target)) {
        return false;
      }
    } else {
      std::ostringstream e;
      e << "could not find TARGET " << *ni
        << ".  Perhaps it has not yet been created.";
      this->SetError(e.str());
      return false;
    }
  }
  return true;
}

bool cmSetPropertyCommand::HandleTarget(cmTarget* target)
{
  // Set or append the property.
  const char* name = this->PropertyName.c_str();
  const char* value = this->PropertyValue.c_str();
  if (this->Remove) {
    value = 0;
  }
  if (this->AppendMode) {
    target->AppendProperty(name, value, this->AppendAsString);
  } else {
    target->SetProperty(name, value);
  }

  // Check the resulting value.
  target->CheckProperty(name, this->Makefile);

  return true;
}

bool cmSetPropertyCommand::HandleSourceMode()
{
  for (std::set<std::string>::const_iterator ni = this->Names.begin();
       ni != this->Names.end(); ++ni) {
    // Get the source file.
    if (cmSourceFile* sf = this->Makefile->GetOrCreateSource(*ni)) {
      if (!this->HandleSource(sf)) {
        return false;
      }
    } else {
      std::ostringstream e;
      e << "given SOURCE name that could not be found or created: " << *ni;
      this->SetError(e.str());
      return false;
    }
  }
  return true;
}

bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf)
{
  // Set or append the property.
  const char* name = this->PropertyName.c_str();
  const char* value = this->PropertyValue.c_str();
  if (this->Remove) {
    value = 0;
  }

  if (this->AppendMode) {
    sf->AppendProperty(name, value, this->AppendAsString);
  } else {
    sf->SetProperty(name, value);
  }
  return true;
}

bool cmSetPropertyCommand::HandleTestMode()
{
  // Look for tests with all names given.
  std::set<std::string>::iterator next;
  for (std::set<std::string>::iterator ni = this->Names.begin();
       ni != this->Names.end(); ni = next) {
    next = ni;
    ++next;
    if (cmTest* test = this->Makefile->GetTest(*ni)) {
      if (this->HandleTest(test)) {
        this->Names.erase(ni);
      } else {
        return false;
      }
    }
  }

  // Names that are still left were not found.
  if (!this->Names.empty()) {
    std::ostringstream e;
    e << "given TEST names that do not exist:\n";
    for (std::set<std::string>::const_iterator ni = this->Names.begin();
         ni != this->Names.end(); ++ni) {
      e << "  " << *ni << "\n";
    }
    this->SetError(e.str());
    return false;
  }
  return true;
}

bool cmSetPropertyCommand::HandleTest(cmTest* test)
{
  // Set or append the property.
  const char* name = this->PropertyName.c_str();
  const char* value = this->PropertyValue.c_str();
  if (this->Remove) {
    value = 0;
  }
  if (this->AppendMode) {
    test->AppendProperty(name, value, this->AppendAsString);
  } else {
    test->SetProperty(name, value);
  }

  return true;
}

bool cmSetPropertyCommand::HandleCacheMode()
{
  if (this->PropertyName == "ADVANCED") {
    if (!this->Remove && !cmSystemTools::IsOn(this->PropertyValue.c_str()) &&
        !cmSystemTools::IsOff(this->PropertyValue.c_str())) {
      std::ostringstream e;
      e << "given non-boolean value \"" << this->PropertyValue
        << "\" for CACHE property \"ADVANCED\".  ";
      this->SetError(e.str());
      return false;
    }
  } else if (this->PropertyName == "TYPE") {
    if (!cmState::IsCacheEntryType(this->PropertyValue.c_str())) {
      std::ostringstream e;
      e << "given invalid CACHE entry TYPE \"" << this->PropertyValue << "\"";
      this->SetError(e.str());
      return false;
    }
  } else if (this->PropertyName != "HELPSTRING" &&
             this->PropertyName != "STRINGS" &&
             this->PropertyName != "VALUE") {
    std::ostringstream e;
    e << "given invalid CACHE property " << this->PropertyName << ".  "
      << "Settable CACHE properties are: "
      << "ADVANCED, HELPSTRING, STRINGS, TYPE, and VALUE.";
    this->SetError(e.str());
    return false;
  }

  for (std::set<std::string>::const_iterator ni = this->Names.begin();
       ni != this->Names.end(); ++ni) {
    // Get the source file.
    cmMakefile* mf = this->GetMakefile();
    cmake* cm = mf->GetCMakeInstance();
    const char* existingValue = cm->GetState()->GetCacheEntryValue(*ni);
    if (existingValue) {
      if (!this->HandleCacheEntry(*ni)) {
        return false;
      }
    } else {
      std::ostringstream e;
      e << "could not find CACHE variable " << *ni
        << ".  Perhaps it has not yet been created.";
      this->SetError(e.str());
      return false;
    }
  }
  return true;
}

bool cmSetPropertyCommand::HandleCacheEntry(std::string const& cacheKey)
{
  // Set or append the property.
  const char* name = this->PropertyName.c_str();
  const char* value = this->PropertyValue.c_str();
  cmState* state = this->Makefile->GetState();
  if (this->Remove) {
    state->RemoveCacheEntryProperty(cacheKey, name);
  }
  if (this->AppendMode) {
    state->AppendCacheEntryProperty(cacheKey, name, value,
                                    this->AppendAsString);
  } else {
    state->SetCacheEntryProperty(cacheKey, name, value);
  }

  return true;
}

bool cmSetPropertyCommand::HandleInstallMode()
{
  cmake* cm = this->Makefile->GetCMakeInstance();

  for (std::set<std::string>::const_iterator i = this->Names.begin();
       i != this->Names.end(); ++i) {
    if (cmInstalledFile* file =
          cm->GetOrCreateInstalledFile(this->Makefile, *i)) {
      if (!this->HandleInstall(file)) {
        return false;
      }
    } else {
      std::ostringstream e;
      e << "given INSTALL name that could not be found or created: " << *i;
      this->SetError(e.str());
      return false;
    }
  }
  return true;
}

bool cmSetPropertyCommand::HandleInstall(cmInstalledFile* file)
{
  // Set or append the property.
  std::string const& name = this->PropertyName;

  cmMakefile* mf = this->Makefile;

  const char* value = this->PropertyValue.c_str();
  if (this->Remove) {
    file->RemoveProperty(name);
  } else if (this->AppendMode) {
    file->AppendProperty(mf, name, value, this->AppendAsString);
  } else {
    file->SetProperty(mf, name, value);
  }
  return true;
}
