#!/usr/bin/env ruby -w

require 'optparse'
require 'rubygems'
require 'hoe'
require 'fileutils'
require 'erb'

XIF = 'FI' + 'X' # prevents extra hits on my TAG reporter

option = {
  :style  => "default",
  :subdir => nil,
}

def check_subdir option
  if option[:subdir] then
    warn "ERROR: you can't specify multiple subdirs"
    abort opts.to_s
  end
end

op = OptionParser.new do |opts|
  opts.banner = "Usage: sow [options] project_name"

  opts.separator "Standard options:"

  opts.on("-t", "--trunk", "Add project to subdir under 'trunk'.") do
    check_subdir option
    option[:subdir] = "trunk"
  end

  opts.on("-d", "--dev", "Add project to subdir under 'dev'.") do
    check_subdir option
    option[:subdir] = "dev"
  end

  opts.on("-s style", "--style style", String, "Use template <style>.") do |s|
    option[:style] = s
  end

  opts.on("-h", "--help", "Show this message.") do
    puts opts
    exit
  end
end

op.parse!

include FileUtils::Verbose

# variables for erb:
template_dir  = File.expand_path("~/.hoe_template")
template_path = File.join template_dir, option[:style]
source_path   = File.join(File.dirname(File.dirname(__FILE__)), "template")
default_dir   = File.join template_dir, "default"

if File.directory? template_dir and not File.directory? default_dir then
  warn "Detected old #{template_dir}"
  warn "Moving to #{default_dir}"
  tmp = "#{template_dir}.#{$$}"
  File.rename template_dir, tmp
  FileUtils.mkdir template_dir
  File.rename tmp, default_dir
end

unless File.directory? template_path then
  warn "Creating missing #{option[:style]} template."
  FileUtils.mkdir_p File.dirname(template_path)
  FileUtils.cp_r source_path, template_path
  paths = (Dir["#{template_path}/**/*"] +
           Dir["#{template_path}/**/.*"]).select { |f| File.file? f }
  FileUtils.chmod 0644, paths
  FileUtils.chmod 0755, paths.grep(/bin\//)
end

project = ARGV.shift

abort op.to_s unless project
abort "Project #{project} seems to exist" if test ?d, project

_, file_name, klass = Hoe.normalize_names project

FileUtils.cp_r template_path, project

Dir.chdir project do
  dirs = Dir["**/*"].select { |f| File.directory? f }.sort.reverse
  dirs.grep(/file_name$/).each do |file|
    FileUtils.mv file, file.sub(/file_name$/, file_name)
  end

  paths = (Dir["**/*"] + Dir["**/.*"]).select { |f| File.file? f }.sort
  paths.each do |path|
    file = File.read path

    warn "erb: #{path}"

    File.open path, "w" do |io|
      erb = ERB.new file
      erb.filename = path
      io.puts erb.result(binding)
    end
  end

  paths.grep(/file_name|\.erb$/).each do |file|
    new_file = file.sub(/file_name/, file_name).sub(/\.erb$/, '')

    # TODO change template to separate a flat filename from a directory
    # filename
    if file =~ /^(bin|test)/ then
      dir, *rest = new_file.split File::SEPARATOR

      new_file = File.join dir, rest.join('_')
    end

    FileUtils.mkdir_p File.dirname new_file
    FileUtils.mv file, new_file
  end
end

if option[:subdir] then
  temp_dir = "#{project}.#{$$}"
  FileUtils.mv project, temp_dir
  FileUtils.mkdir project
  FileUtils.mv temp_dir, "#{project}/#{option[:subdir]}"
end

puts
puts "... done, now go fix all occurrences of '#{XIF}':"
if Hoe::WINDOZE then
  puts `findstr /N /S /C:#{XIF} #{project}\\*`
else
  puts `find #{project} -type f | xargs grep -n #{XIF}`.gsub(/\A|\n/, "\n  ")
end
