#!/usr/bin/ruby

longest_streak = streak = 0

# -- Exit gracefully --
Signal.trap("INT") {
  puts "\nLongest streak: #{longest_streak}"
  exit 0
}

def print_header
  puts "----------------------------------------------------------"
  puts "                      THE GIT GAME                        "
  puts "----------------------------------------------------------"
  puts "Welcome! The goal of the git game is to guess committers"
  puts "based on their commit messages.\n\n"
end

def print_help
  puts "----------------------------------------------------------"
  puts "                          USAGE                           "
  puts "----------------------------------------------------------"
  puts "git game [extra git log options]"
  puts "EX: git game --after={2014-08-08}"
  puts "(This script already uses --no-merges and --pretty."
  puts "For more valid options see: http://gitref.org/inspect/)"
end

# -- Usage Text --
if ARGV.count > 0 && (input = ARGV.shift) == 'help'
  print_header
  print_help
  exit 0
end

# -- Parse commits --
COMMIT_DELIMITER = "XXXCOMMITXXX"
FIELD_DELIMITER = "|||"

commit_format = ["%an", "%ar", "%B"].join(FIELD_DELIMITER)

raw_commits = `git log --no-merges --pretty="#{COMMIT_DELIMITER}#{commit_format}" #{input if input}`.split("#{COMMIT_DELIMITER}")
commits = []
raw_commits.each do |c|
  next if c.strip.empty?

  fields = c.split(FIELD_DELIMITER)
  commits << {:author => fields[0], :date => fields[1], :message => fields[2]}
end

committers = commits.map { |c| c[:author] }.compact.uniq

# -- Show welcome message --
system('clear')

print_header
puts "You're playing in a repo with #{commits.size} commits and #{committers.size}"
puts "distinct committers.\n\n"

committers.each do |committer|
  puts committer
end

puts "Ready? PRESS ENTER TO START PLAYING (Ctrl-C to quit)"

gets

system('clear')

# -- Game loop --
NUM_CHOICE = 4

loop do
  commit = commits.shuffle.pop
  message = commit[:message]
  author = commit[:author]

  next if message.nil? || message.empty? || author.nil? || author.empty?

  puts "(#{commit[:date]})\n"
  puts "#{message.strip}\n\n"
  puts

  choices = committers.sample(NUM_CHOICE)
  if !choices.include?(author)
    choices.pop
    choices.push author
  end
  choices.shuffle!

  choices.each_with_index do |name, index|
    puts "[#{index + 1}] #{name}"
  end

  print "Who wrote it (current streak: #{streak})? "

  guess = gets.strip

  while guess.empty? || !guess.to_i.between?(1, NUM_CHOICE)
    print "Who wrote it (current streak: #{streak})? "
    guess = gets.strip
  end

  if choices[guess.to_i - 1] == author
    streak += 1
    puts "Got it!"
  else
    streak = 0
    puts "Actually, it was #{author}."
  end

  longest_streak = [longest_streak, streak].max

  sleep 1
  system('clear')
end