#ifndef SQUASH_PARSER
#define SQUASH_PARSER

// See License.txt for copyright and terms of use

// Provides patch printing facilities

#include <iostream>
#include <vector>
#include <string>
#include <map>

class MinMaxLineVisitor;
class SquashCmd;

class Patcher {
public:
  Patcher(SquashCmd &cmd);
  ~Patcher();
  void load(std::string const &file);
  void printPatch(std::string const &str, MinMaxLineVisitor const &mmlv,
                  std::string const &file);
  // returns line in file
  std::string getLine(unsigned int line, std::string const &file);

  // returns contents of file specified by mmlv
  std::string getRange(MinMaxLineVisitor const &mmlv);

  unsigned int lineCount(std::string const &file);
  void copy(MinMaxLineVisitor const &mmlv, std::string const &file,
            std::ostream &ostream, std::string const &prefix);

  // Performs a single subsitution, in the future should probably be augmented
  // with regexps to ensure that parts of words aren't replaced
  void replaceWord(MinMaxLineVisitor const &mmlv, std::string const &what,
                   std::string const &with);
  // sets the file from which the relative includes originate
  void setFile(std::string const &file);
  void flush();
private:
  int replaceWord(std::string const &file, int srcline, int minCol,
                  int suggestedCol, std::string const &what, 
                  std::string const &with, std::string srcline,
                  std::string &dest);
  void printHunkHeaderAndDeletedLines(MinMaxLineVisitor const &mmlv,
                                      int added_lines, std::string const &file,
                                      std::ostream &ostream);

  std::string resolveAbsolutePath(std::string const &path) const;

private:
  std::string file;
  std::vector<std::string> lines;
  // (file, (minLine,  hunk))
  typedef std::map<std::string, std::map<unsigned int, std::string> > patch_map; 
  patch_map output;
  typedef std::pair<std::string, std::string> strpair;
  // (file, (minLine, (column, (renameWhat, renameTo))))
  typedef std::map<unsigned int, strpair > RenamesByColumn;
  typedef std::map<unsigned int, RenamesByColumn > RenamesByLine;
  typedef std::map<std::string, RenamesByLine > Renames;
  Renames outputRenames;
  std::string dir;
  SquashCmd &cmd;
};

#endif // SQUASH_PARSER
