require 'optparse'

options = {}

def ensure_key!(m, k)
  if not m.has_key?(k)
    ks = m.keys.map { |k| k.to_s }.join(",")
    raise ArgumentError.new("Required key not set: #{k} (keys: #{ks})")
  end
end

OptionParser.new do |opts|
  opts.on("-c", "--classpath=PATH",
          "Classpath to pass to clojure.") { |cp|
    options[:classpath] = cp
  }

  opts.on("-t", "--target=TARGET",
          "Directory at which to perform the build.") { |target|
    options[:target] = target
  }

  opts.on("-p", "--project=PROJECT",
          "Name of the project being built (eg. org.clojure/build.tools).") { |project|
    options[:project] = project
  }

  opts.on("-v", "--version=VERS",
          "Version of the project being built (eg. 1.0.2).") { |vers|
    options[:version] = vers
  }

  opts.on("-e", "--build-deps=PATH",
          "Location of the build deps.edn, for build-specific dependencies.") { |deps|
    options[:build_deps] = deps
  }

  opts.on("-r", "--root=PATH",
          "Root of the build project, containing deps.edn.") { |path|
    options[:root] = path
  }

  opts.on("-s", "--source-paths=PATHS",
          "Location of the Clojure project to be built.") { |paths|
    options[:sources] = paths.split(",")
  }
end.parse!

[:classpath, :target, :project, :build_deps, :sources, :root, :version].each { |k|
  ensure_key!(options, k)
}

target = options[:target]
if not (File::directory?(target) and File::writable?(target))
  raise ArgumentError.new("Not a valid build target directory: #{target}")
end

options[:sources].each { |path|
  raise ArgumentError.new("Not a valid source path: #{path}") if not (File::directory? path)
}

if not File::exists? "#{options[:root]}/deps.edn"
  raise ArgumentError.new("Does not appear to be project root directory: #{options[:root]}")
end

if not File::exists? "#{options[:build_deps]}"
  raise ArgumentError.new("Build deps.edn not found: #{options[:build_deps]}")
end

command = [
  "clojure",
  "-Scp #{options[:classpath]}",
  "-Sdeps #{options[:build_deps]}",
  "-T:build",
  "lib-uberjar",
  ":project #{options[:project]}",
  ":target #{options[:target]}",
  ":version #{options[:version]}",
  ":srcs #{options[:sources]}"
].join(" ")

Dir::chdir(options[:root]) do
  output = `#{command}`
  puts output
end