require "rubygems"
require "bundler"
require "yaml"

Bundler.setup
Bundler.require

BASEDIR = File.expand_path("../", __FILE__)
CONFIG = YAML.load(IO.read(File.join(BASEDIR, "config.yml")))

require "rack/test"
require "sinatra/base"
require "sinatra_static"
require "redcarpet"
require 'digest/md5'

def md_pre(text)
  text.gsub!(/`([^`]+)`/, '<code>\1</code>')

  text.gsub!(/(^(?! {4}|\t)\w+_\w+_\w[\w_]*)/) do |x|
    x.gsub('_', '\_') if x.split('').sort.to_s[0..1] == '__'
  end

  text.gsub!(/( *){{{([^}]+)}}}/) do |m|
    IO.read(File.join(BASEDIR, $2)).split("\n").map do |l|
      "#{$1}#{l}"
    end.join("\n")
  end

  text
end

def md_post(html)
  html.gsub!('<pre><code>', '<pre class="prettyprint"><code>')
  html
end

class DocApp < Sinatra::Base

  set :public_folder, File.join(BASEDIR, 'assets')
  set :environment, :test
  set :raise_errors, true

  helpers do
    include Rack::Utils
    alias_method :h, :escape_html
  end

  get "/" do
    @yield = render(:erb, IO.read(File.join(BASEDIR, 'index.erb')))
    @body_classes = "colorbg"
    render_with_layout
  end

  get "/chartsql" do
    @yield = render(:erb, IO.read(File.join(BASEDIR, 'index.erb')))
    @body_classes = "colorbg"
    render_with_layout
  end

  get "/examples" do
    @title = "Examples"
    @route = "/index"
    @yield = render(:erb, IO.read(File.join(BASEDIR, 'examples.erb')))
    render_with_layout
  end

  get "/examples/*" do
    params[:splat] ||= ["index"]
    @route = "/#{params[:splat] * "/"}"
    @example = CONFIG["examples"]
        .map { |g| g["examples"].map{ |e| e.merge("group" => g) } }
        .flatten
        .find { |e| e["url"] == @route }
    @title = "Examples"
    @yield = render(:erb, IO.read(File.join(BASEDIR, 'examples.erb')))
    render_with_layout
  end

  def render_documentation(route)
    @route = route
    @page = CONFIG["documentation"]
        .map { |g| g["pages"].map{ |p| p.merge("group" => g) } }
        .flatten
        .find { |p| p["url"] == @route }

    renderer = Redcarpet::Markdown.new(
        Redcarpet::Render::HTML.new(:no_link => true))

    @title = "#{@page["title"]} | Documentation"
    doc_file = File.join(BASEDIR, "../documentation/#{@page["file"]}.md")
    @doc_yield = if File.exists?(doc_file)
      md_post(renderer.render(md_pre(IO.read(doc_file))))
    else
      "file not found #{@page["file"]}"
    end
    @yield = render(:erb, IO.read(File.join(BASEDIR, 'documentation.erb')))

    render_with_layout
  end

  get "/documentation" do
    render_documentation "/"
  end

  get "/documentation/*" do
    render_documentation "/#{params[:splat] * "/"}"
  end

  def render_with_layout
    render :erb, IO.read(File.join(BASEDIR, 'layout.erb'))
  end

end

desc "clean"
task :clean do
  puts "Cleaning up..."
  %x{rm -rf #{BASEDIR}/target}
end

desc "build"
task :build do
  puts "-"*50
  puts "ProTip (TM):\n    $ cd target && python -m SimpleHTTPServer 9090"
  puts "-"*50
  puts nil

  puts "+ Build: FnordMetric Documentation"
  Rake::Task["render"].invoke
  puts "+ Build complete :)"
end

task :render do
  puts "+ Rendering Markdown to HTML"
  builder = SinatraStatic.new(DocApp)
  target = File.join(BASEDIR, "target")

  routes = %w{
    /
    /chartsql
    /documentation
    /examples}

  CONFIG["examples"].each do |example_group|
    example_group["examples"].each do |example|
      routes << "/examples#{example["url"]}"
    end
  end

  CONFIG["documentation"].each do |page_group|
    page_group["pages"].each do |page|
      routes << "/documentation#{page["url"]}"
    end
  end

  routes.each do |path|
    puts "  + #{path}"
    builder.send(:build_path, path, target)
  end

  puts "+ Copying Assets"
  %x{test -e #{BASEDIR}/target/fnordmetric.js || (rm #{BASEDIR}/target/fnordmetric.js; ln -s #{BASEDIR}/../../fnordmetric-js/fnordmetric.js #{BASEDIR}/target)}
  %x{cp -R #{BASEDIR}/assets/* #{BASEDIR}/target}
  %x{cp -R #{BASEDIR}/assets/.htaccess #{BASEDIR}/target}
end

task :publish do
  exec "rsync -Lvr target/ fnordmetric.io:fnordmetric.io"
end

task :publish_staging do
  exec "rsync -Lvr target/ fnordmetric.io:staging.fnordmetric.io"
end

task :default do
  puts "usage: rake [command]"
  puts <<-EOU
  build     # build the static html docs
  clean     # delete all generated files
  publish   # publish to fnordmetric.io
  EOU
end
