#!/usr/bin/env ruby
require 'active_record'
require 'fileutils'
require 'trac4r'

TIME_FILE = "/var/tmp/mpwa-sync"
ROOT = File.expand_path(File.dirname(__FILE__) + "/../") 
NEW_PORTS = "#{ROOT}/bin/new_ports"
PORT_INDEX = "/opt/local/var/macports/sources/rsync.macports.org/release/ports"
RAILS_ROOT = "#{ROOT}/mpwa"
OPEN_STATUSES = ['new', 'reopened', 'assigned']
TRAC_URL = "http://192.168.1.135/svn-helloworld/xmlrpc"
TRAC_USER = "admin"
TRAC_PASS = "turnkey"

require File.expand_path(RAILS_ROOT + '/app/models/category.rb',  __FILE__)
require File.expand_path(RAILS_ROOT + '/app/models/port.rb',  __FILE__)
require File.expand_path(RAILS_ROOT + '/app/models/port_dependency.rb',  __FILE__)
require File.expand_path(RAILS_ROOT + '/app/models/ticket.rb',  __FILE__)

if File.exists?(TIME_FILE)
  $mtime = File.stat(TIME_FILE).mtime.to_i
else
  $mtime = 0
end

FileUtils.touch(TIME_FILE)

$ports = Array.new
$hashed_data = Hash.new

db_info = YAML.load_file(File.expand_path(RAILS_ROOT + '/config/database.yml',  __FILE__))
ActiveRecord::Base.establish_connection(db_info['development'])
trac = Trac.new(TRAC_URL, TRAC_USER, TRAC_PASS)

fp = IO.popen("#{NEW_PORTS} -m #{$mtime} #{PORT_INDEX}")
new_ports = fp.read.split("\n")

if new_ports.count > 0
  new_ports << "" #add last blank line
end

new_ports.each do |line|
  unless (line == "")
    data = line.match(/(\S+):\s+\{?(.+)\}?$/)
    unless data.nil? #field missing, should record this if it happens
      $hashed_data[data[1].to_sym] = data[2]
    end
  else
    category_name = $hashed_data[:categories].try(:split, " ").try(:[], 0)
    $category = Category.find_by_name(category_name)
    if $category.nil?
      $category = Category.new({:name => category_name})
      $category.save
    end

    port = Port.find_by_name($hashed_data[:name])
    if port.nil?
      port = Port.new
    end

    port[:name] = $hashed_data[:name]
    port[:path] = $hashed_data[:portdir]
    port[:version] = $hashed_data[:version]
    port[:description] = $hashed_data[:description]
    port[:licenses] = $hashed_data[:license]
    port[:category_id] = $category.id
    port[:variants] = $hashed_data[:variants]
    port[:maintainers] = $hashed_data[:maintainers]
    port[:platforms] = $hashed_data[:platforms]
    port[:categories] = $hashed_data[:categories]

    $ports << [$hashed_data, port]
    port.save
    $hashed_data = {}
  end
end

$ports.each do |port|
  dependencies = Array.new
  unless port[0][:depends_lib].nil?
    dependencies << port[0][:depends_lib].split(" ")
  end

  unless port[0][:depends_run].nil?
    dependencies << port[0][:depends_run].split(" ")
  end

  unless port[0][:depends_build].nil?
    dependencies << port[0][:depends_build].split(" ")
  end

  dependencies.flatten.uniq.each do |dependency|
    name = dependency.match(/.+:(.+)/)[1]
    dep = Port.find_by_name(name)
    unless dep.nil? #should provide the info that the port doesn't exist eventually
      port[1].port_dependencies.build({:dependency_id => dep.id}).save!
    end
  end
end

var = trac.tickets.changes(Time.at($mtime).to_datetime)
tickets = var.map {|id| trac.tickets.get(id)}
tickets.each do |ticket|
  if ticket.instance_variables.include?(:@port)
    port = Port.find_by_name(ticket.port)
    if OPEN_STATUSES.include?(ticket.status)
      unless (saved_ticket = port.tickets.find_by_ticket(ticket.id)).nil?
        unless saved_ticket.summary == ticket.summary
          saved_ticket = ticket.summary
          saved_ticket.save
        end
      else
        port.tickets.build({:ticket => ticket.id, :summary => ticket.summary}).save
      end
    else
      unless (saved_ticket = port.tickets.find_by_ticket(ticket.id)).nil?
        saved_ticket.destroy
      end
    end
  end
end