// Generated by CoffeeScript 1.9.3
(function() {
  var Actor, Commit, Tree, _;

  _ = require('underscore');

  Actor = require('./actor');

  Tree = require('./tree');

  module.exports = Commit = (function() {
    function Commit(repo1, id1, parents, tree, author1, authored_date1, committer1, committed_date1, gpgsig1, message) {
      this.repo = repo1;
      this.id = id1;
      this.author = author1;
      this.authored_date = authored_date1;
      this.committer = committer1;
      this.committed_date = committed_date1;
      this.gpgsig = gpgsig1;
      this.message = message;
      this.tree = _.memoize((function(_this) {
        return function() {
          return new Tree(_this.repo, tree);
        };
      })(this));
      this.parents = _.memoize((function(_this) {
        return function() {
          return _.map(parents, function(parent) {
            return new Commit(_this.repo, parent);
          });
        };
      })(this));
      this.describe = (function(_this) {
        return function(refs, first_parent, callback) {
          var options, parent, ref1, ref2;
          if (!callback) {
            ref1 = [callback, first_parent], first_parent = ref1[0], callback = ref1[1];
          }
          if (!callback) {
            ref2 = [callback, refs], refs = ref2[0], callback = ref2[1];
          }
          options = {};
          if (refs === "all") {
            options.all = true;
          }
          if (refs === "tags") {
            options.tags = true;
          }
          if (!!first_parent) {
            options.first - (parent = true);
          }
          options.long = true;
          return _this.repo.git("describe", options, _this.id, function(err, stdout, stderr) {
            if (err) {
              return callback(err);
            }
            return callback(null, stdout.trim());
          });
        };
      })(this);
    }

    Commit.prototype.toJSON = function() {
      return {
        id: this.id,
        author: this.author,
        authored_date: this.authored_date,
        committer: this.committer,
        committed_date: this.committed_date,
        message: this.message
      };
    };

    Commit.find_all = function(repo, ref, options, callback) {
      options = _.extend({
        pretty: "raw"
      }, options);
      return repo.git("rev-list", options, ref, (function(_this) {
        return function(err, stdout, stderr) {
          if (err) {
            return callback(err);
          }
          return callback(null, _this.parse_commits(repo, stdout));
        };
      })(this));
    };

    Commit.find = function(repo, id, callback) {
      var options;
      options = {
        pretty: "raw",
        "max-count": 1
      };
      return repo.git("rev-list", options, id, (function(_this) {
        return function(err, stdout, stderr) {
          if (err) {
            return callback(err);
          }
          return callback(null, _this.parse_commits(repo, stdout)[0]);
        };
      })(this));
    };

    Commit.find_commits = function(repo, ids, callback) {
      var commits, next;
      commits = [];
      next = function(i) {
        var id;
        if (id = ids[i]) {
          return Commit.find(repo, id, function(err, commit) {
            if (err) {
              return callback(err);
            }
            commits.push(commit);
            return next(i + 1);
          });
        } else {
          return callback(null, commits);
        }
      };
      return next(0);
    };

    Commit.parse_commits = function(repo, text) {
      var author, author_line, authored_date, commits, committed_date, committer, committer_line, encoding, gpgsig, id, lines, message_lines, parents, ref1, ref2, tree;
      commits = [];
      lines = text.split("\n");
      while (lines.length) {
        id = _.last(lines.shift().split(" "));
        if (!id) {
          break;
        }
        tree = _.last(lines.shift().split(" "));
        parents = [];
        while (/^parent/.test(lines[0])) {
          parents.push(_.last(lines.shift().split(" ")));
        }
        author_line = lines.shift();
        ref1 = this.actor(author_line), author = ref1[0], authored_date = ref1[1];
        committer_line = lines.shift();
        ref2 = this.actor(committer_line), committer = ref2[0], committed_date = ref2[1];
        gpgsig = [];
        if (/^gpgsig/.test(lines[0])) {
          gpgsig.push(lines.shift().replace(/^gpgsig /, ''));
          while (!/^ -----END PGP SIGNATURE-----$/.test(lines[0])) {
            gpgsig.push(lines.shift());
          }
          gpgsig.push(lines.shift());
        }
        while (/^kilnhgcopies/.test(lines[0])) {
          lines.shift();
        }
        while (/^HG:/.test(lines[0])) {
          lines.shift();
        }
        if (/^encoding/.test(lines[0])) {
          encoding = _.last(lines.shift().split(" "));
        }
        if (lines.length) {
          lines.shift();
        }
        message_lines = [];
        while (/^ {4}/.test(lines[0])) {
          message_lines.push(lines.shift().slice(4));
        }
        while ((lines[0] != null) && !lines[0].length) {
          lines.shift();
        }
        commits.push(new Commit(repo, id, parents, tree, author, authored_date, committer, committed_date, gpgsig.join("\n"), message_lines.join("\n")));
      }
      return commits;
    };

    Commit.actor = function(line) {
      var actor, epoch, m, ref1;
      ref1 = /^.+? (.*) (\d+) .*$/.exec(line), m = ref1[0], actor = ref1[1], epoch = ref1[2];
      return [Actor.from_string(actor), new Date(1000 * +epoch)];
    };

    return Commit;

  })();

}).call(this);
