/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2013 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 "cmVisualStudioSlnParser.h"

#include "cmSystemTools.h"
#include "cmVisualStudioSlnData.h"

#include <cassert>
#include <stack>

//----------------------------------------------------------------------------
namespace
{
  enum LineFormat
  {
    LineMultiValueTag,
    LineSingleValueTag,
    LineKeyValuePair,
    LineVerbatim
  };
}

//----------------------------------------------------------------------------
class cmVisualStudioSlnParser::ParsedLine
{
public:
  bool IsComment() const;
  bool IsKeyValuePair() const;

  const std::string& GetTag() const { return this->Tag; }
  const std::string& GetArg() const { return this->Arg.first; }
  std::string GetArgVerbatim() const;
  size_t GetValueCount() const { return this->Values.size(); }
  const std::string& GetValue(size_t idxValue) const;
  std::string GetValueVerbatim(size_t idxValue) const;

  void SetTag(const std::string& tag) { this->Tag = tag; }
  void SetArg(const std::string& arg) { this->Arg = StringData(arg, false); }
  void SetQuotedArg(const std::string& arg)
    { this->Arg = StringData(arg, true); }
  void AddValue(const std::string& value)
    { this->Values.push_back(StringData(value, false)); }
  void AddQuotedValue(const std::string& value)
    { this->Values.push_back(StringData(value, true)); }

  void CopyVerbatim(const std::string& line) { this->Tag = line; }

private:
  typedef std::pair<std::string, bool> StringData;
  std::string Tag;
  StringData Arg;
  std::vector<StringData> Values;
  static const std::string BadString;
  static const std::string Quote;
};

//----------------------------------------------------------------------------
const std::string cmVisualStudioSlnParser::ParsedLine::BadString;
const std::string cmVisualStudioSlnParser::ParsedLine::Quote("\"");

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParsedLine::IsComment() const
{
  assert(!this->Tag.empty());
  return (this->Tag[0]== '#');
}

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParsedLine::IsKeyValuePair() const
{
  assert(!this->Tag.empty());
  return this->Arg.first.empty() && this->Values.size() == 1;
}

//----------------------------------------------------------------------------
std::string cmVisualStudioSlnParser::ParsedLine::GetArgVerbatim() const
{
  if (this->Arg.second)
    return Quote + this->Arg.first + Quote;
  else
    return this->Arg.first;
}

//----------------------------------------------------------------------------
const std::string&
cmVisualStudioSlnParser::ParsedLine::GetValue(size_t idxValue) const
{
  if (idxValue < this->Values.size())
    return this->Values[idxValue].first;
  else
    return BadString;
}

//----------------------------------------------------------------------------
std::string
cmVisualStudioSlnParser::ParsedLine::GetValueVerbatim(size_t idxValue) const
{
  if (idxValue < this->Values.size())
    {
    const StringData& data = this->Values[idxValue];
    if (data.second)
      return Quote + data.first + Quote;
    else
      return data.first;
    }
  else
    return BadString;
}

//----------------------------------------------------------------------------
class cmVisualStudioSlnParser::State
{
public:
  explicit State(DataGroupSet requestedData);

  size_t GetCurrentLine() const { return this->CurrentLine; }
  bool ReadLine(std::istream& input, std::string& line);

  LineFormat NextLineFormat() const;

  bool Process(const cmVisualStudioSlnParser::ParsedLine& line,
               cmSlnData& output,
               cmVisualStudioSlnParser::ResultData& result);

  bool Finished(cmVisualStudioSlnParser::ResultData& result);

private:
  enum FileState
  {
    FileStateStart,
    FileStateTopLevel,
    FileStateProject,
    FileStateProjectDependencies,
    FileStateGlobal,
    FileStateSolutionConfigurations,
    FileStateProjectConfigurations,
    FileStateSolutionFilters,
    FileStateGlobalSection,
    FileStateIgnore
  };
  std::stack<FileState> Stack;
  std::string EndIgnoreTag;
  DataGroupSet RequestedData;
  size_t CurrentLine;

  void IgnoreUntilTag(const std::string& endTag);
};

//----------------------------------------------------------------------------
cmVisualStudioSlnParser::State::State(DataGroupSet requestedData) :
  RequestedData(requestedData),
  CurrentLine(0)
{
  if (this->RequestedData.test(DataGroupProjectDependenciesBit))
    this->RequestedData.set(DataGroupProjectsBit);
  this->Stack.push(FileStateStart);
}

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::State::ReadLine(std::istream& input,
                                              std::string& line)
{
  ++this->CurrentLine;
  return !std::getline(input, line).fail();
}

//----------------------------------------------------------------------------
LineFormat cmVisualStudioSlnParser::State::NextLineFormat() const
{
  switch (this->Stack.top())
    {
    case FileStateStart: return LineVerbatim;
    case FileStateTopLevel: return LineMultiValueTag;
    case FileStateProject: return LineSingleValueTag;
    case FileStateProjectDependencies: return LineKeyValuePair;
    case FileStateGlobal: return LineSingleValueTag;
    case FileStateSolutionConfigurations: return LineKeyValuePair;
    case FileStateProjectConfigurations: return LineKeyValuePair;
    case FileStateSolutionFilters: return LineKeyValuePair;
    case FileStateGlobalSection: return LineKeyValuePair;
    case FileStateIgnore: return LineVerbatim;
    default:
      assert(false);
      return LineVerbatim;
    }
}

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::State::Process(
  const cmVisualStudioSlnParser::ParsedLine& line,
  cmSlnData& output, cmVisualStudioSlnParser::ResultData& result)
{
  assert(!line.IsComment());
  switch (this->Stack.top())
    {
    case FileStateStart:
      if (!cmSystemTools::StringStartsWith(
        line.GetTag().c_str(), "Microsoft Visual Studio Solution File"))
        {
        result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
        return false;
        }
      this->Stack.pop();
      this->Stack.push(FileStateTopLevel);
      break;
    case FileStateTopLevel:
      if (line.GetTag().compare("Project") == 0)
        {
        if (line.GetValueCount() != 3)
          {
          result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
          return false;
          }
        if (this->RequestedData.test(DataGroupProjectsBit))
          {
          if (!output.AddProject(line.GetValue(2),
                                 line.GetValue(0),
                                 line.GetValue(1)))
            {
            result.SetError(ResultErrorInputData, this->GetCurrentLine());
            return false;
            }
          this->Stack.push(FileStateProject);
          }
        else
          this->IgnoreUntilTag("EndProject");
        }
      else if (line.GetTag().compare("Global") == 0)
        this->Stack.push(FileStateGlobal);
      else
        {
        result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
        return false;
        }
      break;
    case FileStateProject:
      if (line.GetTag().compare("EndProject") == 0)
        this->Stack.pop();
      else if (line.GetTag().compare("ProjectSection") == 0)
        {
        if (line.GetArg().compare("ProjectDependencies") == 0 &&
            line.GetValue(0).compare("postProject") == 0)
          {
          if (this->RequestedData.test(DataGroupProjectDependenciesBit))
            this->Stack.push(FileStateProjectDependencies);
          else
            this->IgnoreUntilTag("EndProjectSection");
          }
        else
          this->IgnoreUntilTag("EndProjectSection");
        }
      else
        {
        result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
        return false;
        }
      break;
    case FileStateProjectDependencies:
      if (line.GetTag().compare("EndProjectSection") == 0)
        this->Stack.pop();
      else if (line.IsKeyValuePair())
        // implement dependency storing here, once needed
        ;
      else
        {
        result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
        return false;
        }
      break;
    case FileStateGlobal:
      if (line.GetTag().compare("EndGlobal") == 0)
        this->Stack.pop();
      else if (line.GetTag().compare("GlobalSection") == 0)
        {
        if (line.GetArg().compare("SolutionConfigurationPlatforms") == 0 &&
            line.GetValue(0).compare("preSolution") == 0)
          {
          if (this->RequestedData.test(DataGroupSolutionConfigurationsBit))
            this->Stack.push(FileStateSolutionConfigurations);
          else
            this->IgnoreUntilTag("EndGlobalSection");
          }
        else if (line.GetArg().compare("ProjectConfigurationPlatforms") == 0 &&
                 line.GetValue(0).compare("postSolution") == 0)
          {
          if (this->RequestedData.test(DataGroupProjectConfigurationsBit))
            this->Stack.push(FileStateProjectConfigurations);
          else
            this->IgnoreUntilTag("EndGlobalSection");
          }
        else if (line.GetArg().compare("NestedProjects") == 0 &&
                 line.GetValue(0).compare("preSolution") == 0)
          {
          if (this->RequestedData.test(DataGroupSolutionFiltersBit))
            this->Stack.push(FileStateSolutionFilters);
          else
            this->IgnoreUntilTag("EndGlobalSection");
          }
        else if (this->RequestedData.test(DataGroupGenericGlobalSectionsBit))
          this->Stack.push(FileStateGlobalSection);
        else
          this->IgnoreUntilTag("EndGlobalSection");
        }
      else
        {
        result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
        return false;
        }
      break;
    case FileStateSolutionConfigurations:
      if (line.GetTag().compare("EndGlobalSection") == 0)
        this->Stack.pop();
      else if (line.IsKeyValuePair())
        // implement configuration storing here, once needed
        ;
      else
        {
        result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
        return false;
        }
      break;
    case FileStateProjectConfigurations:
      if (line.GetTag().compare("EndGlobalSection") == 0)
        this->Stack.pop();
      else if (line.IsKeyValuePair())
        // implement configuration storing here, once needed
        ;
      else
        {
        result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
        return false;
        }
      break;
    case FileStateSolutionFilters:
      if (line.GetTag().compare("EndGlobalSection") == 0)
        this->Stack.pop();
      else if (line.IsKeyValuePair())
        // implement filter storing here, once needed
        ;
      else
        {
        result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
        return false;
        }
      break;
    case FileStateGlobalSection:
      if (line.GetTag().compare("EndGlobalSection") == 0)
        this->Stack.pop();
      else if (line.IsKeyValuePair())
        // implement section storing here, once needed
        ;
      else
        {
        result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
        return false;
        }
      break;
    case FileStateIgnore:
      if (line.GetTag() == this->EndIgnoreTag)
        {
        this->Stack.pop();
        this->EndIgnoreTag = "";
        }
      break;
    default:
      result.SetError(ResultErrorBadInternalState, this->GetCurrentLine());
      return false;
    }
  return true;
}

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::State::Finished(
  cmVisualStudioSlnParser::ResultData& result)
{
  if (this->Stack.top() != FileStateTopLevel)
    {
    result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
    return false;
    }
  result.Result = ResultOK;
  return true;
}

//----------------------------------------------------------------------------
void cmVisualStudioSlnParser::State::IgnoreUntilTag(const std::string& endTag)
{
  this->Stack.push(FileStateIgnore);
  this->EndIgnoreTag = endTag;
}

//----------------------------------------------------------------------------
cmVisualStudioSlnParser::ResultData::ResultData()
  : Result(ResultOK)
  , ResultLine(0)
{}

//----------------------------------------------------------------------------
void cmVisualStudioSlnParser::ResultData::Clear()
{
  *this = ResultData();
}

//----------------------------------------------------------------------------
void cmVisualStudioSlnParser::ResultData::SetError(ParseResult error,
                                                   size_t line)
{
  this->Result = error;
  this->ResultLine = line;
}

//----------------------------------------------------------------------------
const cmVisualStudioSlnParser::DataGroupSet
cmVisualStudioSlnParser::DataGroupProjects(
  1 << cmVisualStudioSlnParser::DataGroupProjectsBit);

const cmVisualStudioSlnParser::DataGroupSet
cmVisualStudioSlnParser::DataGroupProjectDependencies(
  1 << cmVisualStudioSlnParser::DataGroupProjectDependenciesBit);

const cmVisualStudioSlnParser::DataGroupSet
cmVisualStudioSlnParser::DataGroupSolutionConfigurations(
  1 << cmVisualStudioSlnParser::DataGroupSolutionConfigurationsBit);

const cmVisualStudioSlnParser::DataGroupSet
cmVisualStudioSlnParser::DataGroupProjectConfigurations(
  1 << cmVisualStudioSlnParser::DataGroupProjectConfigurationsBit);

const cmVisualStudioSlnParser::DataGroupSet
cmVisualStudioSlnParser::DataGroupSolutionFilters(
  1 << cmVisualStudioSlnParser::DataGroupSolutionFiltersBit);

const cmVisualStudioSlnParser::DataGroupSet
cmVisualStudioSlnParser::DataGroupGenericGlobalSections(
  1 << cmVisualStudioSlnParser::DataGroupGenericGlobalSectionsBit);

const cmVisualStudioSlnParser::DataGroupSet
cmVisualStudioSlnParser::DataGroupAll(~0);

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::Parse(std::istream& input,
                                    cmSlnData& output,
                                    DataGroupSet dataGroups)
{
  this->LastResult.Clear();
  if (!this->IsDataGroupSetSupported(dataGroups))
    {
    this->LastResult.SetError(ResultErrorUnsupportedDataGroup, 0);
    return false;
    }
  State state(dataGroups);
  return this->ParseImpl(input, output, state);
}

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseFile(const std::string& file,
                                        cmSlnData& output,
                                        DataGroupSet dataGroups)
{
  this->LastResult.Clear();
  if (!this->IsDataGroupSetSupported(dataGroups))
    {
    this->LastResult.SetError(ResultErrorUnsupportedDataGroup, 0);
    return false;
    }
  std::ifstream f(file.c_str());
  if (!f)
    {
    this->LastResult.SetError(ResultErrorOpeningInput, 0);
    return false;
    }
  State state(dataGroups);
  return this->ParseImpl(f, output, state);
}

//----------------------------------------------------------------------------
cmVisualStudioSlnParser::ParseResult
cmVisualStudioSlnParser::GetParseResult() const
{
  return this->LastResult.Result;
}

//----------------------------------------------------------------------------
size_t cmVisualStudioSlnParser::GetParseResultLine() const
{
  return this->LastResult.ResultLine;
}

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::GetParseHadBOM() const
{
  return this->LastResult.HadBOM;
}

//----------------------------------------------------------------------------
bool
cmVisualStudioSlnParser::IsDataGroupSetSupported(DataGroupSet dataGroups) const
{
  return (dataGroups & DataGroupProjects) == dataGroups;
    //only supporting DataGroupProjects for now
}

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseImpl(std::istream& input,
                                        cmSlnData& output,
                                        State& state)
{
  std::string line;
  // Does the .sln start with a Byte Order Mark?
  if (!this->ParseBOM(input, line, state))
    return false;
  do
    {
    line = cmSystemTools::TrimWhitespace(line);
    if (line.empty())
      continue;
    ParsedLine parsedLine;
    switch (state.NextLineFormat())
      {
      case LineMultiValueTag:
        if (!this->ParseMultiValueTag(line, parsedLine, state))
          return false;
        break;
      case LineSingleValueTag:
        if (!this->ParseSingleValueTag(line, parsedLine, state))
          return false;
        break;
      case LineKeyValuePair:
        if (!this->ParseKeyValuePair(line, parsedLine, state))
          return false;
        break;
      case LineVerbatim:
        parsedLine.CopyVerbatim(line);
        break;
      }
    if (parsedLine.IsComment())
      continue;
    if (!state.Process(parsedLine, output, this->LastResult))
      return false;
    }
    while (state.ReadLine(input, line));
  return state.Finished(this->LastResult);
}

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseBOM(std::istream& input,
                                       std::string& line,
                                       State& state)
{
  char bom[4];
  if (!input.get(bom, 4))
    {
    this->LastResult.SetError(ResultErrorReadingInput, 1);
    return false;
    }
  this->LastResult.HadBOM =
    (bom[0] == char(0xEF) && bom[1] == char(0xBB) && bom[2] == char(0xBF));
  if (!state.ReadLine(input, line))
    {
    this->LastResult.SetError(ResultErrorReadingInput, 1);
    return false;
    }
  if (!this->LastResult.HadBOM)
    line = bom + line;  // it wasn't a BOM, prepend it to first line
  return true;
}

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseMultiValueTag(const std::string& line,
                                                 ParsedLine& parsedLine,
                                                 State& state)
{
  size_t idxEqualSign = line.find('=');
  const std::string& fullTag = line.substr(0, idxEqualSign);
  if (!this->ParseTag(fullTag, parsedLine, state))
    return false;
  if (idxEqualSign != line.npos)
    {
    size_t idxFieldStart = idxEqualSign + 1;
    if (idxFieldStart < line.size())
      {
      size_t idxParsing = idxFieldStart;
      bool inQuotes = false;
      for (;;)
        {
        idxParsing = line.find_first_of(",\"", idxParsing);
        bool fieldOver = false;
        if (idxParsing == line.npos)
          {
          fieldOver = true;
          if (inQuotes)
            {
            this->LastResult.SetError(ResultErrorInputStructure,
                                      state.GetCurrentLine());
            return false;
            }
          }
        else if (line[idxParsing] == ',' && !inQuotes)
          fieldOver = true;
        else if (line[idxParsing] == '"')
          inQuotes = !inQuotes;
        if (fieldOver)
          {
          if (!this->ParseValue(line.substr(idxFieldStart,
                                            idxParsing - idxFieldStart),
                                parsedLine))
            return false;
          if (idxParsing == line.npos)
            break;  //end of last field
          idxFieldStart = idxParsing + 1;
          }
        ++idxParsing;
        }
      }
    }
  return true;
}

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseSingleValueTag(const std::string& line,
                                                  ParsedLine& parsedLine,
                                                  State& state)
{
  size_t idxEqualSign = line.find('=');
  const std::string& fullTag = line.substr(0, idxEqualSign);
  if (!this->ParseTag(fullTag, parsedLine, state))
    return false;
  if (idxEqualSign != line.npos)
    {
    if (!this->ParseValue(line.substr(idxEqualSign + 1), parsedLine))
      return false;
    }
  return true;
}

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseKeyValuePair(const std::string& line,
                                                ParsedLine& parsedLine,
                                                State& /*state*/)
{
  size_t idxEqualSign = line.find('=');
  if (idxEqualSign == line.npos)
    {
    parsedLine.CopyVerbatim(line);
    return true;
    }
  const std::string& key = line.substr(0, idxEqualSign);
  parsedLine.SetTag(cmSystemTools::TrimWhitespace(key));
  const std::string& value = line.substr(idxEqualSign + 1);
  parsedLine.AddValue(cmSystemTools::TrimWhitespace(value));
  return true;
}

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseTag(const std::string& fullTag,
                                       ParsedLine& parsedLine,
                                       State& state)
{
  size_t idxLeftParen = fullTag.find('(');
  if (idxLeftParen == fullTag.npos)
    {
    parsedLine.SetTag(cmSystemTools::TrimWhitespace(fullTag));
    return true;
    }
  parsedLine.SetTag(
    cmSystemTools::TrimWhitespace(fullTag.substr(0, idxLeftParen)));
  size_t idxRightParen = fullTag.rfind(')');
  if (idxRightParen == fullTag.npos)
    {
    this->LastResult.SetError(ResultErrorInputStructure,
                              state.GetCurrentLine());
    return false;
    }
  const std::string& arg = cmSystemTools::TrimWhitespace(
    fullTag.substr(idxLeftParen + 1, idxRightParen - idxLeftParen - 1));
  if (arg[0] == '"')
    {
    if (arg[arg.size() - 1] != '"')
      {
      this->LastResult.SetError(ResultErrorInputStructure,
                                state.GetCurrentLine());
      return false;
      }
      parsedLine.SetQuotedArg(arg.substr(1, arg.size() - 2));
    }
  else
    parsedLine.SetArg(arg);
  return true;
}

//----------------------------------------------------------------------------
bool cmVisualStudioSlnParser::ParseValue(const std::string& value,
                                         ParsedLine& parsedLine)
{
  const std::string& trimmed = cmSystemTools::TrimWhitespace(value);
  if (trimmed.empty())
    parsedLine.AddValue(trimmed);
  else if (trimmed[0] == '"' && trimmed[trimmed.size() - 1] == '"')
    parsedLine.AddQuotedValue(trimmed.substr(1, trimmed.size() - 2));
  else
    parsedLine.AddValue(trimmed);
  return true;
}
