require 'rake/rdoctask'
require 'rake/testtask'
require 'rake/gempackagetask'

# Initialize some variables.

readme = File.read('README')
Release = (readme[/^= (.+) README$/, 1] || 'unknown').downcase.tr(" ", "-")
Name = Release[/\D+/].sub(/\-+$/, '') || 'unknown'
Version = Release[/[\d.]+/] || 'unknown'

AuthorName, AuthorMail = 'George Moschovitis', 'gm@navel.gr'
RubyVersion = '1.8.3' 

# Description = (readme[/README\s+(.+?)\n\n/m, 1] || "unknown").gsub(/\s+/, " ")
# Summary = Description[/^.+?>/] || "unknown"

# DocFiles = %w(README NEWS TODO COPYING GPL)
# RDocFiles = DocFiles - %w(GPL)
RDocOpts = ["--inline-source", "--line-numbers","--title", Name ]
# AdditionalFiles = DocFiles + %w(setup.rb)
VersionFile = MainFile = File.join("lib", Name + '.rb')

RubyForgeProject = Name
RubyForgeUser = 'gmosx'
Homepage = "http://www.nitrohq.org/"

task :default => :package

$NITRO_NO_ENVIRONMENT = true

# Run the tests.

Rake::TestTask.new do |t|
  cwd = File.expand_path(File.join(File.dirname(__FILE__), '..'))
  t.libs << 'test'
  %w[glue nitro og].each do |dir|
    t.libs << File.join(cwd, dir, 'lib')
  end
  t.test_files = FileList['test/**/tc*.rb']
  t.verbose = true
end

# Generate RDoc documentation.

Rake::RDocTask.new do |rd|
  rd.main = 'README'
  rd.rdoc_dir = 'rdoc'
  rd.rdoc_files.include('README', 'INSTALL', 'doc/RELEASES', 'lib/**/*.rb')
  rd.options << '--all --inline-source'
end

# Build gem.

spec = Gem::Specification.new do |s|
  s.name = 'nitro'
  if File.read('lib/nitro.rb') =~ /Version\s+=\s+'(\d+\.\d+\.\d+)'/
    s.version = $1 
  else
    raise 'No version found'
  end
  s.summary = 'Nitro Web Engine'
  s.description = 
    'Nitro provides everything you need to develop real-world, scalable ' +
    'web applications.'

  s.add_dependency 'glue', "= #{s.version}"
  s.add_dependency 'og', "= #{s.version}"
  s.add_dependency 'gen', "= #{s.version}"
  s.add_dependency 'ruby-breakpoint', '= 0.5'
  s.add_dependency 'RedCloth', '= 3.0.3'

  s.required_ruby_version = '= 1.8.3'

  s.files = FileList[
    '[A-Z]*', 'setup.rb', '{bin,benchmark,examples,doc,proto,lib,test,vendor}/**/*' 
  ].exclude("_darcs").exclude("_darcs/**/*").exclude('*.og').exclude('**/*.log').to_a

  s.require_path = 'lib'
  s.autorequire = 'nitro'
  
  s.has_rdoc = true
  s.extra_rdoc_files = FileList['[A-Z]*'].to_a
  s.rdoc_options << '--main' << 'README' << '--title' << 'Nitro Documentation'
  s.rdoc_options << '--all' << '--inline-source'

  s.test_files = []
  
  s.bindir = 'bin'
  s.executables = ['nitro', 'nitrogen']
  s.default_executable = 'nitro'

  s.author = 'George Moschovitis'
  s.email = 'gm@navel.gr'
  s.homepage = 'http://www.nitrohq.com'
  s.rubyforge_project = 'nitro'
end

Rake::GemPackageTask.new(spec) do |pkg|
  pkg.package_dir = 'dist'
  pkg.need_zip = true
  pkg.need_tar = true
end

# Manual install (not recommended).

task :install do
  ruby 'install.rb'
end

# Release files to Rubyforge.
# The code for this task provided by Florian Gross.

desc "Publish the release files to RubyForge."
task :publish => [:package] do
  files = ['gem', 'tgz', 'zip'].map { |ext| "dist/#{Release}.#{ext}" }

  if RubyForgeProject then
    require 'net/http'
    require 'open-uri'

    changes = ''
    if File.exist?('doc/RELEASES') then
      changes_re = /^== \s+ Version \s+ #{Regexp.quote(Version)} \s*
                    (.+?) (?:==|\Z)/mx
      changes = File.read('doc/RELEASES')[changes_re, 1] || ''
    end

    project_uri = "http://rubyforge.org/projects/#{RubyForgeProject}/"
    project_data = open(project_uri) { |data| data.read }
    group_id = project_data[/[?&]group_id=(\d+)/, 1]
    raise "Couldn't get group id" unless group_id

    print "#{RubyForgeUser}@rubyforge.org's password: "
    password = STDIN.gets.chomp

    login_response = Net::HTTP.start('rubyforge.org', 80) do |http|
      data = [
        "login=1",
        "form_loginname=#{RubyForgeUser}",
        "form_pw=#{password}"
      ].join("&")
      http.post('/account/login.php', data)
    end

    cookie = login_response['set-cookie']
    raise 'Login failed' unless cookie
    headers = { 'Cookie' => cookie }

    release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
    release_data = open(release_uri, headers) { |data| data.read }
    package_id = release_data[/[?&]package_id=(\d+)/, 1]
    raise "Couldn't get package id" unless package_id

    first_file = true
    release_id = ""

    files.each do |filename|
      basename = File.basename(filename)
      file_ext = File.extname(filename)
      file_data = File.open(filename, "rb") { |file| file.read }

      puts "Releasing #{basename}..."

      release_response = Net::HTTP.start('rubyforge.org', 80) do |http|
        release_date = Time.now.strftime('%Y-%m-%d %H:%M')
        type_map = {
          '.zip'    => '3000',
          '.tgz'    => '3110',
          '.gz'     => '3110',
          '.gem'    => '1400',
          '.md5sum' => '8100'
        }; type_map.default = '9999'
        type = type_map[file_ext]
        boundary = 'rubyqMY6QN9bp6e4kS21H4y0zxcvoor'

        query_hash = if first_file then
          {
            'group_id' => group_id,
            'package_id' => package_id,
            'release_name' => Release,
            'release_date' => release_date,
            'type_id' => type,
            'processor_id' => '8000', # Any
            'release_notes' => '',
            'release_changes' => changes,
            'preformatted' => '1',
            'submit' => '1'
          }
        else
          {
            'group_id' => group_id,
            'release_id' => release_id,
            'package_id' => package_id,
            'step2' => '1',
            'type_id' => type,
            'processor_id' => '8000', # Any
            'submit' => 'Add This File'
          }
        end

        query = '?' + query_hash.map do |(name, value)|
          [name, URI.encode(value)].join('=')
        end.join('&')

        data = [
          "--" + boundary,
          "Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
          "Content-Type: application/octet-stream",
          "Content-Transfer-Encoding: binary",
          "", file_data, ""
          ].join("\x0D\x0A")

        release_headers = headers.merge(
          'Content-Type' => "multipart/form-data; boundary=#{boundary}"
        )

        target = first_file ? '/frs/admin/qrs.php' : '/frs/admin/editrelease.php'
        http.post(target + query, data, release_headers)
      end

      if first_file then
        release_id = release_response.body[/release_id=(\d+)/, 1]
        raise("Couldn't get release id") unless release_id
      end

      first_file = false
    end
  end
end

# * George Moschovitis  <gm@navel.gr>