#!/usr/bin/ruby

require 'rubygems'
require 'grit'
require 'json'
require 'net/https'

=begin
$stdout.reopen("post-receive.log", "w")
$stdout.sync = true
$stderr.reopen($stdout)
=end

$repo   = Grit::Repo.new(".")
$config = Grit::Config.new($repo)
$giturl = $config['icescrum.giturl']

def generate_payload
  old_commit, new_commit, ref = gets.split()
  {
    :before   => old_commit,
    :after    => new_commit,
    :ref      => ref,
    :commits  => commits(old_commit, new_commit),
    :ref_name => ref.to_s.sub(/\Arefs\/(heads|tags)\//, ''),
    :repository => {
      :name => File.basename(Dir.pwd).sub(/\.git$/,'')
    }
  }
end

def commits(old_commit, new_commit)
  commits = []
  $repo.commits_between(old_commit, new_commit).each do |commit|
    commit_data = {
      :id => commit.sha,
      :author => {
          :name => commit.author.name,
          :email => commit.author.email
        },
        :message => commit.message,
        :timestamp => commit.date.xmlschema
    }
    if $giturl
      $giturl = $giturl[-1,1] == '/' ? $giturl : $giturl +'/'
      commit_data[:url] = $giturl + commit.sha
    end
    commit_data.merge! commit_stats(commit)
    commits << commit_data
  end
  commits
end

def post_data(url, data, username, password)
  uri = URI.parse(url)
  req = Net::HTTP::Post.new(uri.path)
  req.basic_auth username, password
  req.set_form_data(data)
  http = Net::HTTP.new(uri.host, uri.port)

  if uri.scheme == 'https'
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
    http.use_ssl = true
  end

  res = http.start { |http| http.request(req) }
end

def commit_stats(commit)
  stats = {}
  [:added, :removed, :modified].each do |key|
    stats[key] = []
  end

  commit.show.each do |file|
    case
      when added?(file)
        stats[:added] << file.a_path
      when removed?(file)
        stats[:removed] << file.a_path
      when modified?(file)
        stats[:modified] << file.a_path
    end
  end

  stats.delete_if {|key, value| value.nil? }
end

def added?(file)
  file.new_file == true and file.deleted_file == false
end

def removed?(file)
  file.new_file == false and file.deleted_file == true
end

def modified?(file)
  file.new_file == false and file.deleted_file == false
end

project  = $config['icescrum.project'] or raise 'project KEY not set'
url  = $config['icescrum.url'] or raise 'iceScrum URL not set'
username  = $config['icescrum.username'] or raise 'username not set'
password  = $config['icescrum.password'] or raise 'password not set'
url = url[-1,1] == '/' ? url : url +'/'
url  = url + "ws/p/" + project  + "/commit"  
data = { :payload => generate_payload.to_json }

post_data(url, data, username, password)
