#!/usr/bin/env ruby

$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])

help = <<HELP
Jekyll is a blog-aware, static site generator.

Basic Command Line Usage:
  jekyll                                                   # . -> ./_site
  jekyll <path to write generated site>                    # . -> <path>
  jekyll <path to source> <path to write generated site>   # <path> -> <path>
  jekyll import <importer name> <options>                  # imports posts using named import script
  
  Configuration is read from '<source>/_config.yml' but can be overriden
  using the following options:

HELP

require 'optparse'
require 'jekyll'


exec = {}
options = {}
opts = OptionParser.new do |opts|
  opts.banner = help

  opts.on("--file [PATH]", "File to import from") do |import_file|
    options['file'] = import_file
  end
  
  opts.on("--dbname [TEXT]", "DB to import from") do |import_dbname|
    options['dbname'] = import_dbname
  end
  
  opts.on("--user [TEXT]", "Username to use when importing") do |import_user|
    options['user'] = import_user
  end
  
  opts.on("--pass [TEXT]", "Password to use when importing") do |import_pass|
    options['pass'] = import_pass
  end
  
  opts.on("--host [HOST ADDRESS]", "Host to import from") do |import_host|
    options['host'] = import_host
  end
  
  opts.on("--site [SITE NAME]", "Site to import from") do |import_site|
    options['site'] = import_site
  end
  

  opts.on("--[no-]safe", "Safe mode (default unsafe)") do |safe|
    options['safe'] = safe
  end

  opts.on("--[no-]auto", "Auto-regenerate") do |auto|
    options['auto'] = auto
  end

  opts.on("--server [PORT]", "Start web server (default port 4000)") do |port|
    options['server'] = true
    options['server_port'] = port unless port.nil?
  end

  opts.on("--no-server", "Do not start a web server") do |part|
    options['server'] = false
  end

  opts.on("--base-url [BASE_URL]", "Serve website from a given base URL (default '/'") do |baseurl|
      options['baseurl'] = baseurl
  end

  opts.on("--[no-]lsi", "Use LSI for better related posts") do |lsi|
    options['lsi'] = lsi
  end

  opts.on("--[no-]pygments", "Use pygments to highlight code") do |pygments|
    options['pygments'] = pygments
  end

  opts.on("--rdiscount", "Use rdiscount gem for Markdown") do
    options['markdown'] = 'rdiscount'
  end
  
  opts.on("--redcarpet", "Use redcarpet gem for Markdown") do
    options['markdown'] = 'redcarpet'
  end

  opts.on("--kramdown", "Use kramdown gem for Markdown") do
    options['markdown'] = 'kramdown'
  end

  opts.on("--time [TIME]", "Time to generate the site for") do |time|
    options['time'] = Time.parse(time)
  end

  opts.on("--[no-]future", "Render future dated posts") do |future|
    options['future'] = future
  end

  opts.on("--permalink [TYPE]", "Use 'date' (default) for YYYY/MM/DD") do |style|
    options['permalink'] = style unless style.nil?
  end
  
  opts.on("--paginate [POSTS_PER_PAGE]", "Paginate a blog's posts") do |per_page|
    begin
      options['paginate'] = per_page.to_i
      raise ArgumentError if options['paginate'] == 0
    rescue
      puts 'you must specify a number of posts by page bigger than 0'
      exit 0
    end
  end

  opts.on("--limit_posts [MAX_POSTS]", "Limit the number of posts to publish") do |limit_posts|
    begin
      options['limit_posts'] = limit_posts.to_i
      raise ArgumentError if options['limit_posts'] < 1
    rescue
      puts 'you must specify a number of posts by page bigger than 0'
      exit 0
    end
  end

  opts.on("--url [URL]", "Set custom site.url") do |url|
    options['url'] = url
  end

  opts.on("--version", "Display current version") do
    puts "Jekyll " + Jekyll::VERSION
    exit 0
  end
end

# Read command line options into `options` hash
opts.parse!


# Check for import stuff
if ARGV.size > 0
  if ARGV[0] == 'import'
    migrator = ARGV[1]

    if migrator.nil?
      puts "Invalid options. Run `jekyll --help` for assistance."
      exit(1)
    else
      migrator = migrator.downcase
    end
    
    cmd_options = []
    ['file', 'dbname', 'user', 'pass', 'host', 'site'].each do |p|
      cmd_options << "\"#{options[p]}\"" unless options[p].nil?
    end
    
    # It's import time
    puts "Importing..."
    
    # Ideally, this shouldn't be necessary. Maybe parse the actual
    # src files for the migrator name?
    migrators = {
      :posterous => 'Posterous',
      :wordpressdotcom => 'WordpressDotCom',
      :wordpress => 'Wordpress',
      :csv => 'CSV',
      :drupal => 'Drupal',
      :enki => 'Enki',
      :mephisto => 'Mephisto',
      :mt => 'MT',
      :textpattern => 'TextPattern',
      :tumblr => 'Tumblr',
      :typo => 'Typo'
    }
    
    app_root = File.join(File.dirname(__FILE__), '..')
    
    require "#{app_root}/lib/jekyll/migrators/#{migrator}"
    
    if Jekyll.const_defined?(migrators[migrator.to_sym])
      migrator_class = Jekyll.const_get(migrators[migrator.to_sym])
      migrator_class.process(*cmd_options)
    else
      puts "Invalid migrator. Run `jekyll --help` for assistance."
      exit(1)
    end
    
    exit(0)
  end
end



# Get source and destintation from command line
case ARGV.size
  when 0
  when 1
    options['destination'] = ARGV[0]
  when 2
    options['source']      = ARGV[0]
    options['destination'] = ARGV[1]
  else
    puts "Invalid options. Run `jekyll --help` for assistance."
    exit(1)
end

options = Jekyll.configuration(options)

# Get source and destination directories (possibly set by config file)
source      = options['source']
destination = options['destination']

# Files to watch
def globs(source)
  Dir.chdir(source) do
    dirs = Dir['*'].select { |x| File.directory?(x) }
    dirs -= ['_site']
    dirs = dirs.map { |x| "#{x}/**/*" }
    dirs += ['*']
  end
end

# Create the Site
site = Jekyll::Site.new(options)

# Run the directory watcher for auto-generation, if required
if options['auto']
  require 'directory_watcher'

  puts "Auto-regenerating enabled: #{source} -> #{destination}"

  dw = DirectoryWatcher.new(source)
  dw.interval = 1
  dw.glob = globs(source)

  dw.add_observer do |*args|
    t = Time.now.strftime("%Y-%m-%d %H:%M:%S")
    puts "[#{t}] regeneration: #{args.size} files changed"
    site.process
  end

  dw.start

  unless options['server']
    loop { sleep 1000 }
  end
else
  puts "Building site: #{source} -> #{destination}"
  begin
    site.process
  rescue Jekyll::FatalException => e
    puts
    puts "ERROR: YOUR SITE COULD NOT BE BUILT:"
    puts "------------------------------------"
    puts e.message
    exit(1)
  end
  puts "Successfully generated site: #{source} -> #{destination}"
end

# Run the server on the specified port, if required
if options['server']
  require 'webrick'
  include WEBrick

  FileUtils.mkdir_p(destination)

  mime_types = WEBrick::HTTPUtils::DefaultMimeTypes
  mime_types.store 'js', 'application/javascript'

  s = HTTPServer.new(
    :Port            => options['server_port'],
    :MimeTypes       => mime_types
  )
  s.mount(options['baseurl'], HTTPServlet::FileHandler, destination)
  t = Thread.new {
    s.start
  }

  trap("INT") { s.shutdown }
  t.join()
end
